为什么我需要嵌套大括号来编译这段代码?
#include <stdio.h>
#include <stdlib.h>
typedef union TEST TEST;
union TEST {
int type;
char *things;
};
int main () {
TEST test[] = {1, 2, .things = NULL}; // Compile time error
TEST test[] = {1, 2, {.things = NULL}}; // Works, but I didn't check at run time
return 0;
}
为什么第一项作业不起作用?
为什么需要内括号?
有没有办法在第一次任务中工作?没有内括号?
谢谢!
答案 0 :(得分:3)
在前两个元素上不需要内括号的事实是初始化列表的语法中的一个奇怪的细节,它允许将union初始化为其第一个元素。我建议在列表中使用 all 初始值设定项的大括号和名称,而不仅仅是.things
。
答案 1 :(得分:1)
总结:{1, 2, .things = NULL}
尝试初始化名为test
的数组things
的元素,但该数组没有名为things
的元素,所以这是无效的。相反,{1, 2, {.things = NULL}}
尝试初始化名为things
的数组的第二个元素的成员,而数组的第二个元素是具有名为things
的成员的联合。 ,所以这是有效的。
Per C 2011(N1570)6.7.9 17:
每个大括号括起来的初始化列表都有一个关联的当前对象。当没有指定时,根据当前对象的类型按顺序初始化当前对象的子对象:增加下标顺序的数组元素,声明顺序中的结构成员,以及union的第一个命名成员。相反,指定使得以下初始化器开始由指示符描述的子对象的初始化。然后,初始化按顺序继续向前,从指定者描述的下一个子对象开始。
关于如何处理当前对象的后续段落还有更多内容,但现在这已经足够了。在大括号括起的初始化列表中,1
是一个简单的初始值设定项;它没有任何名称。因此它初始化数组的子对象,这是一个数组元素。同样,2
初始化另一个元素。然后我们有.things = NULL
。这确实有一个指示符.things
。
根据引用的段落,该指示符.things
导致.things
描述的子对象的初始化。但是数组中没有任何内容由.things
指定。它只是一个带有索引元素的数组,由[index]
指定。它没有.thigns
指定的任何成员。所以有一个错误。
在第二个列表中,使用了其他大括号,第20段适用:
如果聚合或联合包含聚合或联合的元素或成员,则这些规则将递归地应用于子聚合或包含的联合。如果subaggregate或包含的union的初始值设定项以左括号开头,则该括号括起来的初始值设定项及其匹配的右括号初始化子聚合或所包含联合的元素或成员....
在这种情况下,{.things = NULL}
以左括号开头。这表示大括号中包含的初始值设定项初始化较大列表的当前对象。所以他们正在初始化数组的下一个元素(索引为2的元素)。数组的任何元素都是一个名为things
的成员的联合,因此.things
确实在其中指定了一个子对象,并且这种语法是可以接受的。