在GCC C中使用标记联合为何出现多余元素警告?
C语言匿名联合初始化警告问题
我在C语言中定义了一个包含匿名联合的结构体:
struct uuid_0000000000061d0c { long _0; union { struct {void* _1;}; struct {char* _1001; char* _1002;}; struct {char* _2001;}; struct {}; }; };
该联合包含四个匿名结构体。当我用包含两个字段的“大”结构体初始化实例时,编译器抛出警告:warning: excess elements in struct initializer,初始化代码如下:
struct uuid_0000000000061d0c an_instance = { 1, "a", "b" };
我尝试将联合中字段数最多的匿名结构体移到开头,调整后的定义如下:
struct uuid_0000000000061d0c { long _0; union { struct {char* _1001; char* _1002;}; struct {void* _1;}; struct {char* _2001;}; struct {}; }; };
调整后警告消失了。请问这是编译器警告的bug,还是我误解了该警告的意图?
解答
这不是编译器的bug,是C语言聚合初始化规则的正常表现。
C语言里用花括号做聚合初始化时,处理匿名联合的逻辑是:默认以联合的第一个成员作为初始化的目标类型。
你最开始的代码里,联合第一个成员是仅含一个void*字段的结构体,编译器默认按这个单字段结构体匹配初始化值,但你传入了两个字符串字面量,超出了该成员的字段数量,因此触发“初始化器元素过多”的警告。
把双字段的结构体移到联合开头后,编译器默认以这个双字段结构体作为初始化目标,此时传入的两个值刚好匹配其字段数量,警告自然消失。
如果不想调整联合成员顺序,也可以用C11的指定初始化语法,明确指定要初始化的字段,让编译器精准定位目标成员,示例代码如下:
struct uuid_0000000000061d0c an_instance = { ._0 = 1, ._1001 = "a", ._1002 = "b" };
这样就不会再出现匹配错误的警告了。
内容的提问来源于stack exchange,提问作者Andrew Johnson
相关产品推荐
相关产品推荐

