【问题标题】:C99 Structure Designated Initialisers and other valueC99 结构体指定初始化器和其他值
【发布时间】:2014-10-12 18:03:06
【问题描述】:

我知道在 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。如果我们做这样的复合初始化是什么原因。

【问题讨论】:

    标签: c initialization structure c99 designated-initializer


    【解决方案1】:

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

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

    为什么i 被初始化为0 包含在段落19中,它说:

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

    请注意,正如 Keith 指出的那样,gcc 使用 -Wextra 对此提供了警告:

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

    clang 似乎默认会对此发出警告。

    【讨论】:

      【解决方案2】:

      如果发生

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

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

      【讨论】:

      • 所以即使我用 10.11 初始化 f 现在它也会被设置为 6,对吧?
      • @Sagrian;是的。旧值将被覆盖。
      • gcc 使用 -Wextra-Woverride-init 对此发出警告。
      【解决方案3】:

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2023-03-12
        • 2021-05-26
        • 2015-10-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-04-16
        相关资源
        最近更新 更多