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
答案 0 :(得分:0)
对于第一个问题
您无法直接写入数组,只能将单个单元格写入数组。 您可以使用for循环初始化数组b或memcpy(& b,& a,sizeof b);
使用结构,编译器会为你做memcpy。
如果我错了,请纠正我。
答案 1 :(得分:0)
当您键入:b=a
时,编译器希望您将数组分配给b,但a
只是指向存储数组的第一个元素的位置的指针,因此存在类型不匹配。这就是printf("%d",*a);
将打印1
的原因。
至于为什么可以分配结构,这是因为上例中的b1
和b2
基本上是数据类型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
。这证明此示例中的b
和c
并未指向同一个内存。这有助于。
答案 2 :(得分:0)
赋值要求编译器知道所赋值的类型和大小。所以形式的分配
a = b;
要求a
和b
的类型对于编译器都是已知的。如果类型相同(例如a
和b
均为int
类型),则编译器可以通过任何指令简单地将b
复制到a
中认为最有效。如果类型不同,但是允许隐式升级或类型转换,则在升级后也可以进行分配。例如,如果a
的类型为long
,而b
的类型为short
,则b
将隐式提升为long
,并且促销结果存储在a
中。
这不适用于数组,因为不一定知道数组的大小(以其元素的大小乘以元素的数量计算)。一个编译单元(也就是源文件)可能有一个声明(可能包括一个头文件)
extern int a[];
extern int b[];
void some_func()
{
a = b;
}
告诉编译器a
和b
是int
的数组,但是它们将由另一个编译单元定义(包括给它们提供大小)。然后,另一个编译单元可以这样做;
extern int a[];
int a[] = {3,1,4,2,3}; /* definition of a */
和第三个编译单元可以类似地将b
定义为27个元素的数组。
将目标文件链接到单个可执行文件后,所有编译单元中a
和b
的用法都将关联,并且对它们的所有操作都引用相同的定义。
出现此问题的原因是,单独的编译模型是C的核心功能。因此,当编译器仔细查看上述第一个编译单元时,由于没有其他数组的可见性,因此没有有关数组大小的信息。编译单元,并且需要成功或不参考错误进行诊断。由于没有关于第一个编译单元可用的任一数组中元素数量的信息,因此无法计算出要从一个数组复制到另一个数组中的元素数量。在C中对此的处理是,赋值a = b
是函数some_func()
中可诊断的错误。
还有其他方法(某些其他编程语言对这种情况的处理方式也不同),但它们通常与其他权衡取舍有关。
注意事项通常不会影响struct
类型,因为它们的大小在编译时就已知。因此,如果a
和b
具有相同的struct
类型,则赋值a = b
是可能的,并且可以通过(例如)调用{{1}来实现}。
注意:我在上面的解释中做了一些过分的简化,例如不考虑具有灵活数组成员(来自C99)的结构的情况。讨论此类情况将使上面的讨论更加复杂,而不会改变核心考虑因素。