在C中以C v / s复制结构复制数组

时间:2013-08-18 06:06:12

标签: arrays structure copying

C中的数组和结构将内存中的数据存储为连续的。那么为什么C不允许使用“=”直接复制数组,因为它允许结构。 例如:

int a[3] = {1,2,3};
int b[3];
b = a; // why is this not allowed. 

struct book b1, b2;
b1.page = 100;
b1.price = 10.0;

b2 = b1; // Why is this allowed

3 个答案:

答案 0 :(得分:0)

对于第一个问题

您无法直接写入数组,只能将单个单元格写入数组。 您可以使用for循环初始化数组b或memcpy(& b,& a,sizeof b);

使用结构,编译器会为你做memcpy。

如果我错了,请纠正我。

答案 1 :(得分:0)

当您键入:b=a时,编译器希望您将数组分配给b,但a只是指向存储数组的第一个元素的位置的指针,因此存在类型不匹配。这就是printf("%d",*a);将打印1的原因。 至于为什么可以分配结构,这是因为上例中的b1b2基本上是数据类型book的变量,并且可以赋值变量。当变量被赋值时是复制的,他们不会引用相同的内存位置。这个例子可以解释我说的更清楚:

#include<stdio.h>

typedef struct{int a;}num;
int main()
{
    num b,c;
    b.a = 10;
    c=b;
    b.a =11;
    printf("%d\n",(c.a));
    return 0;
}

输出为10。这证明此示例中的bc并未指向同一个内存。这有助于。

答案 2 :(得分:0)

赋值要求编译器知道所赋值的类型和大小。所以形式的分配

 a = b;

要求ab的类型对于编译器都是已知的。如果类型相同(例如ab均为int类型),则编译器可以通过任何指令简单地将b复制到a中认为最有效。如果类型不同,但是允许隐式升级或类型转换,则在升级后也可以进行分配。例如,如果a的类型为long,而b的类型为short,则b将隐式提升为long,并且促销结果存储在a中。

这不适用于数组,因为不一定知道数组的大小(以其元素的大小乘以元素的数量计算)。一个编译单元(也就是源文件)可能有一个声明(可能包括一个头文件)

 extern int a[];
 extern int b[];

 void some_func()
 {
      a = b;
 }

告诉编译器abint的数组,但是它们将由另一个编译单元定义(包括给它们提供大小)。然后,另一个编译单元可以这样做;

 extern int a[];

 int a[] = {3,1,4,2,3};    /*  definition of a */

和第三个编译单元可以类似地将b定义为27个元素的数组。

将目标文件链接到单个可执行文件后,所有编译单元中ab的用法都将关联,并且对它们的所有操作都引用相同的定义。

出现此问题的原因是,单独的编译模型是C的核心功能。因此,当编译器仔细查看上述第一个编译单元时,由于没有其他数组的可见性,因此没有有关数组大小的信息。编译单元,并且需要成功或不参考错误进行诊断。由于没有关于第一个编译单元可用的任一数组中元素数量的信息,因此无法计算出要从一个数组复制到另一个数组中的元素数量。在C中对此的处理是,赋值a = b是函数some_func()中可诊断的错误。

还有其他方法(某些其他编程语言对这种情况的处理方式也不同),但它们通常与其他权衡取舍有关。

注意事项通常不会影响struct类型,因为它们的大小在编译时就已知。因此,如果ab具有相同的struct类型,则赋值a = b是可能的,并且可以通过(例如)调用{{1}来实现}。

注意:我在上面的解释中做了一些过分的简化,例如不考虑具有灵活数组成员(来自C99)的结构的情况。讨论此类情况将使上面的讨论更加复杂,而不会改变核心考虑因素。