将整个数组传递给函数

Par*_*ita 9 c

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

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

Alc*_*ive 17

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

如果我写:

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]);
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

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


nmi*_*els 8

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


Jon*_*ler 5

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

如果你真的想传递一个数组,请将其包装在一个结构中:

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));
}
Run Code Online (Sandbox Code Playgroud)