为什么在结构体数组中不需要使用花括号初始化?

5
这段代码:
#include <stdio.h>

struct
{
    int i;
    const char* str;
} ar[] = {
    1,"asd", //should be {1, "asd"},
    2, "qwe", //should be {2, "qwe"},
    3, "poi" //should be {3,"poi"}
};

int main()
{
    printf("%s\n", ar[2].str);
}

代码可以正常工作,即使数组ar的每个元素应该用大括号括起来(至少我认为是这样的)。为什么这是可能的?


3
向后兼容性。 因为早期的C语言是这样实现的,标准化后的C语言尽可能要与早期的源代码兼容。 - Jonathan Leffler
2
从来不知道。很棒的发现。 - user14063792468
2个回答

3

6.7.9 Initialization/20 说明了如何初始化结构体元素:

[...] 如果子聚合体或包含的联合体的初始化器以左大括号开头,则被该括号和匹配的右大括号包围的初始化器将初始化子聚合体或包含的联合体的元素或成员。否则,只有来自列表中足够数量的初始化器才会被用来初始化子聚合体或包含联合体的第一个成员;任何剩余的初始化器都将留给初始化当前子聚合体或包含联合体所在的聚合体的下一个元素或成员。

(强调是我加的)

因此这是有效的。因此

ar[] = {
    1,"asd",
    2, "qwe",
    3, "poi"
};

等价于:

 ar[] = {
    {1,"asd"},
    {2, "qwe"},
    {3, "poi"}
};

ar 包含3个元素。


1

很可能是因为标准允许,所以这是有可能的。

那么,为什么标准要允许呢?我不知道是否有任何理由。最有可能的原因是出于向后兼容性考虑。C语言实际上充满了这种情况。

然而,这被认为是不良风格。所以要避免使用。如果启用编译警告(你必须这样做),则会收到以下警告:

warning: missing braces around initializer [-Wmissing-braces]
    7 | } ar[] = {
      |          ^
    8 |     1,"asd", //should be {1, "asd"},
      |     {      }
    9 |     2, "qwe", //should be {2, "qwe"},
      |     {       }
   10 |     3, "poi" //should be {3,"poi"}
      |     {
   11 | };
      | }

C语言背后的哲学与许多其他编程语言非常不同。即使省略大括号是一种不好的风格,但可以说没有真正禁止省略它们的理由。例如,它不会导致任何歧义。


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