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
当您键入 :b=a
时,编译器希望您将一个数组分配给 b,但a
它只是一个指向存储数组第一个元素的位置的指针,因此类型不匹配。这就是为什么printf("%d",*a);
会 print 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
在这个例子中没有指向同一个内存。希望这会有所帮助。
对于第一个问题
您不能直接写入数组,只能将单个单元格写入数组。您可以使用 for 循环来初始化数组 b 或 memcpy(&b, &a, sizeof b);
使用这些结构,编译器会为您执行 memcpy。
如果我错了,请纠正我。
赋值要求编译器知道要赋值的任何内容的类型和大小。所以形式的分配
a = b;
要求编译器知道a
和的类型。b
如果类型相同(例如,两者a
都b
属于 type 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
是可能的 - 并且可以通过(比如说)调用memcpy()
.
注意:我在上面的解释中故意进行了一些过度简化,例如不考虑具有灵活数组成员的结构的情况(来自 C99)。在不改变核心考虑的情况下,讨论此类案例会使上述讨论更加复杂。