14

我知道在 C99 中,您可以使用成员名称初始化结构的成员,如下所示:

struct myStruct
{
 int i;
 char c;
 float f;
};

所以以下是有效的:

struct myStruct m = {.f = 10.11, .i = 5, .c = 'a'};

据说未初始化的成员将被设置为0. 所以

struct myStruct m = {.f = 10.11, .c = 'a'};

这里i将设置为0

但是,对于以下内容:

struct myStruct m = {.f = 10.11, .c = 'a', 6}; 

i仍然初始化为0。如果我们这样做复合初始化是什么原因。

4

3 回答 3

14

这在草案 C99 标准部分6.7.8 Initialization中有所介绍,基本上,如果以下初始化程序不是指示符,那么它将使用该指示符之后的下一个字段,对于您的示例来说,它将是f. 我们可以看一下第17段,它说(强调我的):

每个大括号括起来的初始值设定项列表都有一个关联的当前对象。当没有指定时,当前对象的子对象根据当前对象的类型按顺序初始化:数组元素按递增下标顺序,结构成员按声明顺序,以及联合的第一个命名成员。129)相反,指定会导致下面的初始化程序开始初始化指定符所描述的子对象。然后初始化按顺序继续向前,从指示符描述的下一个子对象开始.130)

第19段介绍了为什么i要初始化为:0

初始化应按初始化程序列表顺序进行,为特定子对象提供的每个初始化程序都将覆盖同一子对象的任何先前列出的初始化程序;132) 所有 未显式初始化的子对象都应隐式初始化,与具有静态存储持续时间的对象相同。

请注意,正如基思指出的那样gcc,为此使用提供了警告-Wextra

warning: initialized field overwritten [-Woverride-init]
 struct myStruct m = {.f = 10.11, .c = 'a', 6}; 
        ^

并且clang默认情况下似乎对此发出警告。

于 2014-08-19T15:05:53.327 回答
6

的情况下

struct myStruct = {.f = 10.11, .c = 'a', 6};   

6非指定初始化器的值将在使用指定初始化器初始化的成员之后分配给该成员。因此,在这种情况下,成员f就在之后c,因此它将被初始化为6. i默认情况下仍将初始化为0

于 2014-08-19T15:05:39.270 回答
0

这里,6 是非指定初始化器。所以,这个值被初始化为紧跟在前一个指定初始化器之后的成员,也就是紧跟在 char 之后的浮点数。

如果您有两个或多个串联的非指定初始化器,则非指定初始化器将被初始化为从最后一个指定初始化器开始的串联成员。

于 2014-08-19T16:07:05.547 回答