【问题标题】:array of struct is passed by value rather than reference结构数组按值而不是引用传递
【发布时间】:2013-01-28 16:45:09
【问题描述】:

使用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'

为什么会这样?

【问题讨论】:

    标签: c


    【解决方案1】:

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

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

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

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

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

    【讨论】:

    • 你和@tletnes 有两个完全不同的答案
    • @Tom 不。实际上答案是一样的。我的比 tletnes 长一点。你知道声明指针和数组的区别吗?
    • @Tom 我现在更新了上面的解释,希望这能澄清它......
    【解决方案2】:

    在第一种情况下,您的结构包含一个指向字符缓冲区的指针,在第二种情况下,结构实际上包含(读取:有空间容纳)20 个字符。

    所以在第一种情况下,当您通过值传递时,您复制的是指针,而不是值。

    【讨论】:

      【解决方案3】:

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

      这并不完全正确。根本不传递数组,没有函数可以将数组作为参数。当你声明了一个函数时

      void foo(int bar[]);
      

      foo 采用的参数类型实际上是int *,以及何时调用它

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

      一个指向arr 的第一个元素的指针按值传递。在 C 中,所有函数参数均按值传递,无一例外。

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

      【讨论】:

      • 嗯,对不起丹尼尔,但我不明白你的反对意见。您获得指向数组的指针而不是在函数中获得数组副本的事实正是引用调用的意思。因此可以说数组总是通过引用传递,因为它们总是通过指向第一个元素的指针传递。
      • @junix:这不是传递引用。如果是这样,在foo() 中修改bar(指针)也会修改调用者框架中的arr。事实并非如此,因为它不是按引用传递。
      • 你没有得到一个指向数组的指针,你得到了一个指向它的第一个元素的指针。虽然效果与通过引用传递数组非常相似,但从语言的角度来看,没有数组通过引用传递,而是指针通过值传递。函数参数的类型不是对数组的引用,而是指向元素的指针。
      • @netcoder 更改数组的内容以使其对调用者可见是传递引用不更改数组基数的指标。尽管如此,我认为我们可以同意传递指针允许通过引用模拟调用。
      猜你喜欢
      • 2015-11-25
      • 1970-01-01
      • 2015-11-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-05-25
      • 1970-01-01
      • 2012-02-26
      相关资源
      最近更新 更多