这通常被建议,作为将结构体初始化为零值的方法:
struct foo f = {0};
还提到{}可以在gcc下使用,但这不是标准的C99.
我想知道这是否适用于一个结构,其布局可能会超出我的控制范围.我很担心,因为0不是数组或结构的有效初始值设定项.但是,即使在这种情况下,gcc –std = c99(gcc-8.1.1-1.fc28.x86_64)似乎也接受{0}.
问题C99是否接受{0}作为任何结构的初始值设定项?
(或者是后来的C标准?或者是否相反,是否有任何理由不依赖于此?是否存在{0}可能导致错误或警告会阻止其使用的编译器?)
我试过了什么
gcc警告(用-Wall启用)表明这是标准中的某种形式的边缘情况,其中gcc被强制接受0作为任何类型的struct字段的初始化器,但除非你使用它,否则它会警告它常见的{0}成语.
struct a { int i; }; struct b { struct a a; struct a a2; }; struct c { int i[1]; int j[1]; }; struct a a = {0}; /* no error */ struct b b = {0}; /* no error */ struct c c = {0}; /* no error */ /* warning (no error): missing braces around initializer [-Wmissing-braces] */ struct b b2 = {0,0}; /* warning (no error): missing braces around initializer [-Wmissing-braces] */ struct c c2 = {0,0}; struct a a2 = 0; /* error: invalid initializer */ int i[1] = 0; /* error: invalid initializer */
解决方法
是的,这是完全有效的.
所有标量类型(整数类型,浮点类型和指针类型)都接受0作为初始化.这不是标量类型的基本属性,但它恰好适用于所有类型.
所有聚合类型(数组和结构)和联合类型都至少有一个成员或元素.第一个成员或元素是标量类型,或者是另一个聚合或联合类型.如果是前者,则使{0}成为有效的初始化者.如果是后者,则应用相同的逻辑:也将至少有一个成员或元素.要么是标量类型,要么是另一种聚合或联合类型.继续.没有办法拥有无限嵌套的结构,所以你总是会以标量类型结束.
非标准语言扩展可能会使这些假设无效.例如,语言扩展可以定义强类型的枚举类型,它们不接受0作为初始化,或者是空结构,或者是零长度数组.