3

为什么在示例代码中使用复合文字(案例 b)定义结构后可以分配结构,而数组不能(案例 c))?

我知道情况 a) 不起作用,因为此时编译器不知道分配的 rhs 上的内存布局。它可以是任何类型的演员表。但是按照这条线,在我看来,案例 c) 是一个完全明确的情况。

typedef struct MyStruct {
  int a, b, c;
} MyStruct_t;

void function(void) {
  MyStruct_t st;
  int arr[3];

  // a) Invalid
  st = {.a=1, .b=2, .c=3};
  // b) Valid since C90
  st = (MyStruct_t){.a=1, .b=2, .c=3};
  // c) Invalid
  arr = (int[3]){[0]=1, [1]=2, [2]=3};
}

编辑:我知道我不能分配给一个数组——这就是 C 的设计方式。我可以使用 memcpy 或单独分配值。

在阅读了下面的评论和答案之后,我想现在我的问题分解为一个永远争论不休的难题,即为什么不能分配给数组。

正如这篇文章和下面MM的评论所建议的那样,更令人费解的是,以下分配是完全有效的(当然,它违反了严格的别名规则)。您可以将数组包装在结构中并进行一些讨厌的转换来模仿可分配数组。

typedef struct Arr3 {
  int a[3];
} Arr3_t;

void function(void) {
  Arr3_t a; 
  int arr[3];

  a = (Arr3_t){{1, 2, 3}};
  *(Arr3_t*)arr = a;
  *(Arr3_t*)arr = (Arr3_t){{4, 5, 6}};
}

那么是什么阻止开发人员将这样的功能包含在C22(?)

4

2 回答 2

5

C根本没有数组的赋值。也就是说,array任何数组类型的 wherearray = /* something here */都是无效的,无论“something here”的内容如何。它是否是复合文字(您似乎与指定的初始化程序混淆了,这是一个完全不同的概念)是无关紧要的。array1 = array2将同样无效。

至于为什么它无效,在某种程度上,这是 C 语言及其设计的动机/基本原理的问题,无法回答。但是,从机械上讲,除了“衰减”sizeof的操作数或&“衰减”的操作数之外的任何上下文中的数组都指向指向其第一个元素的指针。所以在以下情况下:

arr = (int[3]){[0]=1, [1]=2, [2]=3};

您正在尝试将指向复合文字数组的第一个元素的指针分配给非左值(arr衰减时产生的右值)。当然,这是无稽之谈。

于 2020-06-10T18:06:12.903 回答
3

可以在可以使用实际数组变量的任何地方使用复合数组文字。由于您不能将一个数组分配给另一个数组,因此将复合文字分配给数组也是无效的。

由于您可以使用 复制数组memcpy(),因此您可以编写:

memcpy(arr, (int[3]){[0]=1, [1]=2, [2]=3}, sizeof(arr));

就像数组变量一样,数组字面量衰减为指向其第一个元素的指针。

复合结构字面量也可以用来代替实际的结构变量。但是结构可以相互分配,因此将复合结构文字分配给结构变量是有效的。

这就是两种情况的区别。

于 2020-06-10T18:09:15.910 回答