将整个数组传递给函数

时间:2020-11-28 23:20:06

When we pass an element of an array to a function, it is treated as an normal variable and the called function creates a copy of the actual argument and operates on it. Any changes made in the formal arguments doesn't affect the actual arguments.

当我们将一个数组的元素传递给一个函数时,它被视为一个普通变量,被调用的函数创建一个实际参数的副本并对其进行操作。在形式参数中进行的任何更改都不会影响实际参数。

But this not the case when we pass a whole array. In this case it (called function) gets access to the actual arguments and any changes made in the formal arguments affects the actual arguments. Why this happens?

但是当我们传递整个数组时,情况并非如此。在这种情况下,它(称为函数)可以访问实际参数,并且正式参数中的任何更改都会影响实际参数。为什么会这样?

8 个解决方案

#1


16  

The array is passed as a pointer to the elements.

该数组作为指向元素的指针传递。

If I write:

如果我写:

void doStuff(int *ptr)
{
  ptr[1] = 5;
}

int main()
{
  int arr[] = {0, 1, 2};
  doStuff(arr);
  printf("%d %d %d\n", arr[0], arr[1], arr[2]);
}

the output will be "0 5 2". That's because C passes whatever is actually the parameter by value. The parameter is a pointer to an int. So a pointer to an int is passed by value. Thus, doStuff gets a copy of a pointer to memory in main's stack frame. When it dereferences that pointer with ptr[1], it is following the pointer to main's memory and modifying the array there.

输出将为“0 5 2”。那是因为C通过值传递任何实际参数。该参数是指向int的指针。因此,指向int的指针按值传递。因此,doStuff在main的堆栈帧中获取指向内存的指针的副本。当它用ptr [1]取消引用该指针时,它跟随指向main的内存并在那里修改数组。

C can only pass by value, but it does so "shallowly". If you ask it to pass an int *, it will pass an int *. It only copies the value of the pointer, not the values of anything it points to.

C只能通过值传递,但它“浅”。如果要求它传递int *,它将传递一个int *。它只复制指针的值,而不是它指向的任何值。

If you want doStuff to get its own copy of the array, either wrap the array in a struct as others have suggested, or use memcpy to manually deep copy the array like this:

如果你想让doStuff获得它自己的数组副本,要么像其他人建议的那样将数组包装在结构中,要么使用memcpy手动深度复制数组,如下所示:

void doStuff(int *ptr, int nElems)
{
  int myCopyOfTheArray[nElems];
  memcpy(myCopyOfTheArray, ptr, sizeof(int) * nElems);
  /* do stuff with the local copy */
}

Unlike using a struct, the memcpy approach works if nElems is only know at runtime.

与使用结构不同,如果只在运行时知道nElems,则memcpy方法有效。

#2


8  

Arrays can't be passed by value in C. They get demoted to pointers. So the called function sees a pointer to the array (passed by reference) and operates on it. If you want to make a copy, you have to either do so explicitly, or put your array inside a struct (which can be passed by value to functions.)

数组不能通过C中的值传递。它们被降级为指针。因此被调用的函数看到一个指向数组的指针(通过引用传递)并对其进行操作。如果要创建副本,则必须显式执行此操作,或将数组放在结构中(可以通过值传递给函数。)

#3


5  

It is expensive to make a copy of a whole array, in general. Back in the days when C was first created, it could easily exhaust the machine resources (stack in particular).

通常,制作整个阵列的副本是昂贵的。回到C首次创建的日子,它可能很容易耗尽机器资源(特别是堆栈)。

If you really want to pass an array, wrap it in a structure:

如果您确实想要传递数组,请将其包装在结构中:

struct wrap { int array[100]; };

int somefunc(struct wrap large) { ... }

void anotherfunc(void)
{
    struct wrap a;
    ...add data to array...
    printf("%d\n", somefunc(a));
}

#4


3  

I haven't really seen any answers yet cover the whole question yet. From what I see, it looks like the question asks something like this:

我还没有看到任何答案,但尚未涵盖整个问题。从我看到的,看起来问题是这样的:

Given the following code:

给出以下代码:

int a[5];

foo(a);
bar(a[0]);

Why can foo manipulate the original values while bar receives only a copy of the value being passed in?

为什么foo可以操作原始值而bar只接收传入值的副本?

This is because of the use of array notation: the [] operator dereferences the item it references in the array and passes in the value at that location.

这是因为使用了数组表示法:[]运算符取消引用它在数组中引用的项目并传入该位置的值。

So

int a[5];
bar(a[0]);

is different than:

不同于:

int* a;
bar(a);

If you want to pass in a references to a specific item in an array, you need to use the & operator:

如果要传递对数组中特定项的引用,则需要使用&运算符:

bar(&a[5]);

#5


2  

"Pass by reference" is a red herring in C. All arguments to a function are "passed by value" only. In case of arrays, you pass the address of the first element in the form of a pointer. You can then use this pointer to refer to the desired memory location & read or write values.

“通过引用传递”是C中的红色鲱鱼。函数的所有参数都只是“按值传递”。在数组的情况下,您以指针的形式传递第一个元素的地址。然后,您可以使用此指针指向所需的内存位置以及读取或写入值。

#6


2  

From the online C standard:

从在线C标准:

6.3.2.1 Lvalues, arrays, and function designators
...
3 Except when it is the operand of the sizeof operator or the unary & operator, or is a string literal used to initialize an array, an expression that has type "array of type" is converted to an expression with type "pointer to type" that points to the initial element of the array object and is not an lvalue. If the array object has register storage class, the behavior is undefined.

Assume the following code snippet:

假设以下代码段:

int a[10];
...
foo(a);

In the call to foo, the type of the expression a is "10-element array of int". However, since the expression is not the operand of either the sizeof or & operators, and since it isn't a string literal being used to initialize another array in a declaration, its type is implicitly converted ("decays") from "10-element array of int" to "pointer to int", and its value will be the address of the first element in the array (i.e. &a[0]).

在对foo的调用中,表达式a的类型是“10元素数组的int”。但是,由于表达式不是sizeof或&运算符的操作数,并且因为它不是用于初始化声明中的另一个数组的字符串文字,所以它的类型从“10-”隐式转换(“衰减”) int“to”指向int“的元素数组,其值将是数组中第一个元素的地址(即&a [0])。

Therefore, what foo receives is a pointer to int, not an array. Dereferencing or subscripting this pointer allows you to change the values of the array.

因此,foo接收的是指向int的指针,而不是数组。取消引用或下标此指针允许您更改数组的值。

This is a feature of the C language; arrays are not first-class objects. In fact, in most circumstances (including subscripting) array expressions will be converted to pointer types.

这是C语言的一个特性;数组不是第一类对象。实际上,在大多数情况下(包括下标),数组表达式将被转换为指针类型。

I keep emphasizing the word expression to distinguish between the actual array object (which is always and forever an array type) and any reference to that object in the code, which may be converted to a pointer type.

我一直在强调单词表达式,以区分实际的数组对象(永远是永远的数组类型)和代码中对该对象的任何引用,可以将其转换为指针类型。

#7


0  

Because when You pass a whole array to function You pass a pointer to that array, which means that You give function a place in memory where this array is located. So when You change the array in function You are changing the original array as well.

因为当你将整个数组传递给函数时你传递一个指向该数组的指针,这意味着你给函数一个位于这个数组所在的内存中的位置。因此,当您在函数中更改数组时,您也在更改原始数组。

#8


0  

An array in C may be treated as a pointer to the first element of the array. The pointer is passed by-value (you cannot modify the value passed in), but you can dereference it and modify the memory that it points at.

C中的数组可以被视为指向数组第一个元素的指针。指针按值传递(您无法修改传入的值),但您可以取消引用它并修改它指向的内存。

#1


16  

The array is passed as a pointer to the elements.

该数组作为指向元素的指针传递。

If I write:

如果我写:

void doStuff(int *ptr)
{
  ptr[1] = 5;
}

int main()
{
  int arr[] = {0, 1, 2};
  doStuff(arr);
  printf("%d %d %d\n", arr[0], arr[1], arr[2]);
}

the output will be "0 5 2". That's because C passes whatever is actually the parameter by value. The parameter is a pointer to an int. So a pointer to an int is passed by value. Thus, doStuff gets a copy of a pointer to memory in main's stack frame. When it dereferences that pointer with ptr[1], it is following the pointer to main's memory and modifying the array there.

输出将为“0 5 2”。那是因为C通过值传递任何实际参数。该参数是指向int的指针。因此,指向int的指针按值传递。因此,doStuff在main的堆栈帧中获取指向内存的指针的副本。当它用ptr [1]取消引用该指针时,它跟随指向main的内存并在那里修改数组。

C can only pass by value, but it does so "shallowly". If you ask it to pass an int *, it will pass an int *. It only copies the value of the pointer, not the values of anything it points to.

C只能通过值传递,但它“浅”。如果要求它传递int *,它将传递一个int *。它只复制指针的值,而不是它指向的任何值。

If you want doStuff to get its own copy of the array, either wrap the array in a struct as others have suggested, or use memcpy to manually deep copy the array like this:

如果你想让doStuff获得它自己的数组副本,要么像其他人建议的那样将数组包装在结构中,要么使用memcpy手动深度复制数组,如下所示:

void doStuff(int *ptr, int nElems)
{
  int myCopyOfTheArray[nElems];
  memcpy(myCopyOfTheArray, ptr, sizeof(int) * nElems);
  /* do stuff with the local copy */
}

Unlike using a struct, the memcpy approach works if nElems is only know at runtime.

与使用结构不同,如果只在运行时知道nElems,则memcpy方法有效。

#2


8  

Arrays can't be passed by value in C. They get demoted to pointers. So the called function sees a pointer to the array (passed by reference) and operates on it. If you want to make a copy, you have to either do so explicitly, or put your array inside a struct (which can be passed by value to functions.)

数组不能通过C中的值传递。它们被降级为指针。因此被调用的函数看到一个指向数组的指针(通过引用传递)并对其进行操作。如果要创建副本,则必须显式执行此操作,或将数组放在结构中(可以通过值传递给函数。)

#3


5  

It is expensive to make a copy of a whole array, in general. Back in the days when C was first created, it could easily exhaust the machine resources (stack in particular).

通常,制作整个阵列的副本是昂贵的。回到C首次创建的日子,它可能很容易耗尽机器资源(特别是堆栈)。

If you really want to pass an array, wrap it in a structure:

如果您确实想要传递数组,请将其包装在结构中:

struct wrap { int array[100]; };

int somefunc(struct wrap large) { ... }

void anotherfunc(void)
{
    struct wrap a;
    ...add data to array...
    printf("%d\n", somefunc(a));
}

#4


3  

I haven't really seen any answers yet cover the whole question yet. From what I see, it looks like the question asks something like this:

我还没有看到任何答案,但尚未涵盖整个问题。从我看到的,看起来问题是这样的:

Given the following code:

给出以下代码:

int a[5];

foo(a);
bar(a[0]);

Why can foo manipulate the original values while bar receives only a copy of the value being passed in?

为什么foo可以操作原始值而bar只接收传入值的副本?

This is because of the use of array notation: the [] operator dereferences the item it references in the array and passes in the value at that location.

这是因为使用了数组表示法:[]运算符取消引用它在数组中引用的项目并传入该位置的值。

So

int a[5];
bar(a[0]);

is different than:

不同于:

int* a;
bar(a);

If you want to pass in a references to a specific item in an array, you need to use the & operator:

如果要传递对数组中特定项的引用,则需要使用&运算符:

bar(&a[5]);

#5


2  

"Pass by reference" is a red herring in C. All arguments to a function are "passed by value" only. In case of arrays, you pass the address of the first element in the form of a pointer. You can then use this pointer to refer to the desired memory location & read or write values.

“通过引用传递”是C中的红色鲱鱼。函数的所有参数都只是“按值传递”。在数组的情况下,您以指针的形式传递第一个元素的地址。然后,您可以使用此指针指向所需的内存位置以及读取或写入值。

#6


2  

From the online C standard:

从在线C标准:

6.3.2.1 Lvalues, arrays, and function designators
...
3 Except when it is the operand of the sizeof operator or the unary & operator, or is a string literal used to initialize an array, an expression that has type "array of type" is converted to an expression with type "pointer to type" that points to the initial element of the array object and is not an lvalue. If the array object has register storage class, the behavior is undefined.

Assume the following code snippet:

假设以下代码段:

int a[10];
...
foo(a);

In the call to foo, the type of the expression a is "10-element array of int". However, since the expression is not the operand of either the sizeof or & operators, and since it isn't a string literal being used to initialize another array in a declaration, its type is implicitly converted ("decays") from "10-element array of int" to "pointer to int", and its value will be the address of the first element in the array (i.e. &a[0]).

在对foo的调用中,表达式a的类型是“10元素数组的int”。但是,由于表达式不是sizeof或&运算符的操作数,并且因为它不是用于初始化声明中的另一个数组的字符串文字,所以它的类型从“10-”隐式转换(“衰减”) int“to”指向int“的元素数组,其值将是数组中第一个元素的地址(即&a [0])。

Therefore, what foo receives is a pointer to int, not an array. Dereferencing or subscripting this pointer allows you to change the values of the array.

因此,foo接收的是指向int的指针,而不是数组。取消引用或下标此指针允许您更改数组的值。

This is a feature of the C language; arrays are not first-class objects. In fact, in most circumstances (including subscripting) array expressions will be converted to pointer types.

这是C语言的一个特性;数组不是第一类对象。实际上,在大多数情况下(包括下标),数组表达式将被转换为指针类型。

I keep emphasizing the word expression to distinguish between the actual array object (which is always and forever an array type) and any reference to that object in the code, which may be converted to a pointer type.

我一直在强调单词表达式,以区分实际的数组对象(永远是永远的数组类型)和代码中对该对象的任何引用,可以将其转换为指针类型。

#7


0  

Because when You pass a whole array to function You pass a pointer to that array, which means that You give function a place in memory where this array is located. So when You change the array in function You are changing the original array as well.

因为当你将整个数组传递给函数时你传递一个指向该数组的指针,这意味着你给函数一个位于这个数组所在的内存中的位置。因此,当您在函数中更改数组时,您也在更改原始数组。

#8


0  

An array in C may be treated as a pointer to the first element of the array. The pointer is passed by-value (you cannot modify the value passed in), but you can dereference it and modify the memory that it points at.

C中的数组可以被视为指向数组第一个元素的指针。指针按值传递(您无法修改传入的值),但您可以取消引用它并修改它指向的内存。