在C语言中复制数组与在C语言中复制结构的比较

问题描述 投票:0回答:3

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
arrays structure copying
3个回答
0
投票

对于第一个问题

你不能直接写到一个数组,只能写到数组的各个单元。你可以使用for循环来初始化数组b或者memcpy(&b, &a, sizeof b)。

而对于结构体,编译器会帮你完成memcpy。

如果我说的不对,请纠正我。


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 在这个例子中,并不是指向同一个内存,希望能帮到你。


0
投票

赋值要求编译器知道被赋值的东西的类型和大小。 所以一个赋值的形式是

 a = b;

的类型要求。ab 都是编译器已知的。 如果类型相同(例如,两者都是 ab 属于 int),那么编译器可以简单地复制 b 变成 a 由任何它认为最有效的指令。 如果类型不同,但允许隐式推广或类型转换,那么做完推广后也可以进行赋值。 例如,如果 a 属于 longb 属于 short那么 b 将被暗中提升为 long 以及该次推广的结果存储在 a.

这对于数组来说是行不通的,因为数组的大小(计算方法是元素的大小乘以元素的数量)不一定是已知的。一个编译单元(也就是源文件)可以有一个声明(可能通过包含一个头文件)

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

 void some_func()
 {
      a = b;
 }

它告诉编译器 ab 的数组。int但它们将被另一个编译单元定义(包括给它们一个大小)。 然后,另一个编译单元可以这样做。

 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 是可能的--并且可以通过(比如)对 memcpy().

注:我在上面的解释中故意做了一些过于简单的解释,比如没有考虑具有灵活数组成员的结构的情况(来自C99)。讨论这种情况会使上面的讨论变得更加复杂,但不会改变核心考虑因素。

© www.soinside.com 2019 - 2024. All rights reserved.