双花括号在C结构体中的初始化有什么意义?

22

我目前正在处理遗留的C++代码,该代码成功地使用gcc 2.9.X编译。
我被要求将这个遗留代码移植到gcc 3.4.X。大多数错误都很容易纠正,但是这个特定的错误让我感到困惑。

背景:

 struct TMessage 
   {
    THeader header;
    TData data;
   };

 struct THeader
   {
    TEnum myEnum;
    TBool validity;
   };

做了什么:

 const TMessage init = {{0}};

 /* Later in the code ... */
 TMessage message = init;

我的问题:
{{}}运算符的含义是什么?它是否将第一个字段(即标题)初始化为二进制0?它是否将第一个结构(即enum)的第一个字段初始化为(文字)0?

我遇到的3.4.6错误是invalid conversion from 'int' to 'TEnum',无论使用一对还是两对花括号都会出现。

如何在不使用memset的情况下将我的结构设置为一堆0?

提前致谢。


为什么你要将代码从旧版的gcc移植到另一个旧版的gcc? - Björn Pollex
在另一个平台上编译/链接/执行它。 - Isaac Clarke
不了解C++。在C语言中没有错误(也许你的编译器过于热心,以至于出现了错误)。 - pmg
你真的不应该尝试编写多语言源文件。这比它所值得的要花费更多的精力。选择一种语言(C或C++...或D或Eiffel或Forth或...),并坚持使用它。 - pmg
正如我所说的,这是遗留代码,除了在3.4.6中无法编译的内容,我没有权利更改任何内容。否则我会同意你的观点 ;) - Isaac Clarke
SunOS 3.4 C(不是C ++)在1987年肯定支持{{}}初始化语法。很可能它在1985年左右也支持。 - Acceptable Name
3个回答

25

它将POD结构的所有字段初始化为0。

原理:

const SomeStruct init = {Value};

初始化SomeStruct的第一个字段为Value,其余部分均为零(我忘记标准中的章节了,但它肯定在某处)

因此:

const SomeOtherStruct init = {{Value}};

将结构体的第一个字段(其中第一个字段本身是POD结构)的第一个字段初始化为Value,将第一个字段的其余部分设置为零,并将结构的其余部分设置为0。

此外,这只是由于C++禁止将int类型隐式转换为枚举类型,因此您可以执行以下操作:

const SomeOtherStruct init = {{TEnum(0)}};

1
那么你的意思是 const TMessage init = {{myEnumFirstValue}}; 会初始化我的枚举,然后将其他所有字段都初始化为0?它可以成功编译,但我现在担心运行时。无论如何,谢谢! - Isaac Clarke
3
标准的相关章节是8.5.1.7:如果初始化列表中的初始值少于聚合体中的成员数,则未明确初始化的每个成员都应该被值初始化。 - Björn Pollex
最后一部分是什么意思?“由编译器进行值初始化”是什么意思? - Isaac Clarke
1
据我所知,在这种情况下,值初始化始终意味着默认构造,这意味着对于简单类型设置为0。(我非常确定其他所有内容最终都会变成零...) - James
4
如果没有默认构造函数,所有非静态成员(包括基类的成员)都将进行值初始化(这基本上是递归地进行)。对于基本类型,值初始化意味着零初始化(这是递归的终止)。 - Björn Pollex
显示剩余2条评论

3
  • 第一个大括号是给struct TMessage用的。
  • 第二个大括号是给struct THeader用的。
  • 数字0是给TEnum myEnum用的。

在这种情况下,您正在使用int 0初始化TEnum,这是不兼容的转换。

因此,您必须像这样添加强制转换:

const TMessage init = {{TEnum(0)}};

在C/C++中,如果你 部分初始化 结构体或数组(只有前面的一些字段或元素),其余部分将由 默认构造函数 初始化(对于原始类型来说,这是零初始化)。如果没有默认构造函数或构造函数被声明为 private,则会出现编译错误。

1
不正确的是,剩余部分并不总是被初始化为零。正如我在对@Autopulated答案的评论中所述,它们将被值初始化。例如,如果其中一个成员是具有默认构造函数的类类型,则将调用该构造函数。 - Björn Pollex

1
你可以把它想象成一个多维数组(如果这有帮助的话)。然后,你可以使用该命令将两个维度重置为0。这是有效的,因为(我假设)结构体中的值可以取0作为值。

谢谢!我错过了每个其他字段都被初始化为0的事实。 - Isaac Clarke

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接