struct的数组是通过值而不是引用传递的

时间:2013-01-28 16:45:09

标签: c

使用this指南我被告知数组是通过引用传递的。当结构看起来像这样时,这就成立了:

struct Person{
 char* name;
 int id;
}

但结构看起来不是这样的:

struct Person{
 char name[20];
 int id;
}

使用seconds结构时,name数组按值复制:

struct Person p1 = {"John", 1234};
struct Person p2 = p1;
p2.name[0] = 'L';

// p1.name[0] is still 'K'

为什么会这样?

3 个答案:

答案 0 :(得分:3)

  

有人告诉我,数组是通过引用传递的。

这不是真的。根本没有传递数组,没有函数可以将数组作为参数。当你声明了一个函数

void foo(int bar[]);

foo所采用的参数类型实际上是int *,当您调用它时

int arr[23];
/* fill arr with meaningful values */
foo(arr);

指向arr的第一个元素的指针按值传递。所有函数参数都通过C中的值传递,无异常。

因此,当您将struct Person传递给函数时,会按值传递,因此会复制struct的成员。如果其中一个成员是一个数组,那么它也被复制,因为它是struct的一部分。

答案 1 :(得分:1)

这适用于两者。唯一的区别是,对于第一个结构,您只存储指向字符串和id字段的指针。在第二个结构中,您将整个字符串和id字段存储在结构中。因此,第一个结构是约。 8个字节的大小(假设一个32位指针),第二个结构是大约。 24字节大小。

在这两种情况下,如果您调用函数并按值传递,则会复制整个结构。您可以通过修改id字段而不是name字段来检查它。

通过引用(作为指针)将结构和数组传递给函数的原因是为了避免将这个副本放到堆栈上。

编辑: 要清除:通过访问第一个结构的p2.name [0],您可以访问内存中其他位置(未复制)的(复制)结构之外的位置。如果为第二个结构访问p2.name [0],则访问为(复制的)结构分配的内存区域内的位置。

检查您的代码我刚刚找到了另一个值得注意的关键部分: 当您使用String文字(硬编码字符串)初始化frist结构时,写入p2.name [0]会导致未定义的行为(取决于工具链和操作系统,您的程序甚至可能因此而崩溃!)

答案 2 :(得分:0)

在第一种情况下,你的struct保存一个指向chars缓冲区的指针,在第二种结构中实际包含(read:有空间保存)20个字符。

因此,在第一种情况下,当您传递值时,您正在复制指针,而不是值。