【问题标题】:Copying array in C v/s copying structure in C在 C 中复制数组与在 C 中复制结构
【发布时间】:2013-08-20 05:05:50
【问题描述】:

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


【解决方案1】:

分配要求编译器知道要分配的任何内容的类型和大小。所以表格的赋值

 a = b;

要求编译器知道ab 的类型。如果类型相同(例如ab 的类型都是int),那么编译器可以通过它认为最有效的任何指令简单地将b 复制到a。如果类型不同,但允许隐式提升或类型转换,则在进行提升后也可以进行赋值。例如,如果along 类型,而bshort 类型,则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 是可能的 - 并且可以通过(例如)调用 memcpy() 来实现。

注意:我在上面的解释中故意过度简化,例如不考虑具有灵活数组成员的结构的情况(来自 C99)。在不改变核心考虑的情况下,讨论此类案例会使上述讨论更加复杂。

【讨论】:

    【解决方案2】:

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

    #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 没有指向同一个内存。希望对您有所帮助。

    【讨论】:

      【解决方案3】:

      第一个问题

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

      编译器会使用这些结构为您执行 memcpy。

      如果我错了,请纠正我。

      【讨论】:

        猜你喜欢
        • 2023-03-10
        • 1970-01-01
        • 2016-06-11
        • 1970-01-01
        • 1970-01-01
        • 2015-05-31
        • 1970-01-01
        • 2019-04-13
        • 1970-01-01
        相关资源
        最近更新 更多