当由值馈送到函数时,结构的数组字段是否会被完全克隆?

Does the array field of a struct get entirely cloned when fed by value to a function?

提问人:Dorin Botan 提问时间:9/13/2018 最后编辑:alkDorin Botan 更新时间:9/13/2018 访问量:568

问:

在 C 中:

  • 结构体通过值(通过参数)发送到函数时,将创建一个新的结构体,因此更改函数内部的结构不会改变原始结构

  • 当数组按值(通过参数)发送到函数时,会创建一个新指针,因此更改函数内部的数组不会更改原始数组,但更改函数内的数组值(因为我们有指向原始数组的指针)将更改原始数中的值。

  • 当带有数组字段的结构体按值(通过参数)发送到函数时,将创建?????,因此更改函数中的数组(指针)不会更改原始数组,更改数组值也不会更改原始数组中的值。

第三点是否意味着结构体的数组字段在发送到函数时将被完全克隆?为什么不只使用指针?规范对此有何规定?

我玩过的一段代码:

typedef struct {
    int value;
    int array[3]; /* initialized to 0 by default */
} Struct_t;

void foo(Struct_t structure)
{
    printf("-- %p\n", structure.array); /* Pointer to local array */

    structure.value = 1;
    *structure.array = 1;       /* Won't change the original array */
    *(structure.array + 1) = 1; /* Won't change the original array */
    structure.array[2] = 1;     /* Won't change the original array */
}

int main()
{
    Struct_t s = { .value = 0 };

    foo(s);

    printf("-- %p\n", s.array); /* Pointer to original array */

    printf("%d\n", s.value);
    printf("%d\n", s.array[0]);
    printf("%d\n", s.array[1]);
    printf("%d\n", s.array[2]);
}

输出:

-- 0x7ffe8f17d194
-- 0x7ffe8f17d1b4
0
0
0
0
C 数组 指针 结构 传递

评论

3赞 mch 9/13/2018
数组是结构的一部分,因此它也将被复制(其中的所有值)。如果它是指针,则只会复制指针,因此将指向与原始内存相同的内存。
0赞 alk 9/13/2018
"更改函数内部的数组不会更改原始数组,但更改函数内部的数组值“”数组它的”“/”元素“,仅此而已。

答:

0赞 kiran Biradar 9/13/2018 #1

一切都是按价值传递的。C

  1. 当我们传递值时,我们将变量的副本传递给函数。

  2. 当我们通过引用传递时,我们将变量的别名传递给函数。

    它正在将指针的值(地址)复制到函数中。

如果 按值传递给函数,则 的 被复制为函数参数。在函数中对此所做的任何事情都会更改副本,而不是原始副本structbytesstructstructstruct

评论

0赞 Dorin Botan 9/13/2018
这是否意味着结构中的数组将完全是该结构的一部分,而不仅仅是指向内存中其他位置的值的指针?似乎是这样,因为 sizeof(struct) 是结构中数组中所有元素的大小之和。但是这样做有具体的原因吗?这不会可能导致性能问题吗?
0赞 Dorin Botan 9/13/2018
我知道 K&R 中不允许按值传递 s,并且是后来添加的。新规范对此有何说明?数组实际上是什么,为什么会这样?structstruct
0赞 001 9/13/2018
@DorinBotan 数组是结构的一部分。用于验证(注意:可能比预期的要大 - 请参阅为什么结构体的 sizeof 不等于每个成员的 sizeof 之和?sizeof(Struct_t))
0赞 Kami Kaze 9/13/2018 #2

结构体是内存的预发现结构,具有一定的内存布局。通过向结构中添加数组,数组的实际内存位于结构中,而不是指针中。这就是为什么它必须与结构的其余部分一起复制的原因。

数组不是指针,数组具有特定的不可更改的内存位置,而指针可以指向您想要的任何位置。

2赞 alk 9/13/2018 #3

第三点是否意味着结构体的数组字段在发送到函数时将被完全克隆?

是的。

为什么不只使用指针?

因为没有指针。数组不是指针。(更多相关内容请点击此处。)

5赞 chux - Reinstate Monica 9/13/2018 #4

OP 的“发送数组时...”需要澄清。

当数组按值(通过参数)发送到函数时,会创建一个新指针,因此更改函数内部的数组不会更改原始数组,但更改函数内的数组值(因为我们有指向原始数组的指针)将更改原始数组中的值。(OP)

当一个数组(如下所示)被传递给 时,首先发生转换。该对象将转换为数组中第一个元素的地址。 不作为参数接收,而是接收 的值的副本。s[]strcpy(char *s1, const char *s2)sstrcpy()s[]s1&s[0]

char s[6] = "Hello";
strcpy(s, "World");

在 中,不是一个数组。 是指向 的指针。 没有“更改函数内部的数组”的概念,因为函数不知道数组内存、分配内存或其他任何东西的点。 理解指向 .strcpy()s1s1charstrcpy()s1strcpy()s1char


第三点是否意味着结构体的数组字段在发送到函数时将被完全克隆?

是的。当一个对象被传递给 C 中的函数时,它可能会被转换,然后按值传递。这很像任何任务。转换后,对象的内容将复制到目标。转换后,如果对象是 etc 或包含数组的结构,则没有区别。struct, union, int, double, void*, int(*)()

int a;
double b;
a = 5;  // 5 is copied to a
b = a;  // a is converted to double and copied to b


char s[6] = "Hello";
char *e;
void *v;
e = s; // s is converted to the address on the first array element and then copied to e
v = e; // e is converted to a `void*` and then copied to v

Struct_t f = {0};
Struct_t g;
g = f; // f is copied to g