使用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'
为什么会这样?
答案 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个字符。
因此,在第一种情况下,当您传递值时,您正在复制指针,而不是值。