C:嵌套花括号在结构体数组初始化中的工作原理是什么?

15
struct mystruct s[10] = {{0}};

这似乎是将结构体数组初始化为0。嵌套大括号的语法是如何工作的?

4个回答

11

任何未指定的字段都会初始化为零。因此,这里有一个结构体数组。您正在使用结构体初始化程序初始化数组的第一个元素,并将结构体的第一个元素初始化为零。第一个结构体的其余部分和数组元素的其余部分也将全部为零。这是一个不错的惯用语。


只是为了确保我理解得正确。由于所有未指定的字段都被初始化为零,因此 = {{0}} 实际上没有任何影响? - jay.lee
4
它确实有影响。它会将第一个元素初始化为零,然后隐式地将其余元素初始化为零。如果省略了{{0}},并且在函数内部(在堆栈上)声明,则会得到随机垃圾值。请注意,如果将其声明为全局变量并省略{{0}},它也将被初始化为零,但原因不同。 - xscott

6

如下所示?

基本上,您应该将每个复合类型 - 数组、结构等 - 包含在自己的花括号层级中。

请考虑:

struct mystruct
{
    int i;
    double d;
    char   s[10];
    int    a[5];
} s[10] =
{
      { 0, 0.0, "abc", { 1, 2, 3, 4, 5 } },
      { 1, 1.0, "def", { 2, 3          } }, // Partially initialized array
      { 2, 2.0, { 'x', 'y', 'z' }, { 0 } }, // Strings are a shorthand
[9] = { 9, 99,  0,     { 9, 8, 7, 6, 5 } }, // C99 - initialize row 9
};

但是如果你坚持的话,也可以省略花括号(这是不好的、过时的做法):
struct mystruct t[3] =
{ // You cannot avoid using these outside braces
  0, 0.00, "abc", 1, 2, 3, 4, 5,  // Omitted braces
  1, 1.11, "bcd", 2, 3, 4, 5, 4,
  2, 2.34,                        // Omitted values
};

任何省略的初始化值都被视为零。


2
使用大括号的一个优点是,它允许您省略某些成员的部分初始化(这些成员将隐式地初始化为零),同时继续初始化后面的成员。您使用 { 'x','y','z' } 就是一个例子。 - R.. GitHub STOP HELPING ICE

5

不是嵌套的花括号进行初始化。外部花括号表示正在初始化数组:

struct mystruct s[10] = {           };

由于这是一个结构数组,因此每个结构都可以使用更多的大括号进行初始化:

struct mystruct { int x, y, z};

struct mystruct s[10] = { {0, 1, 2}, // <-- initializes s[0].x, s[0].y, s[0].z
                          {1, 2, 3}, // <-- initializes s[1].x, s[1].y, s[1].z
                          {2, 3, 4}  // <-- initializes s[2].x, s[2].y, s[2].z
};

请注意,只有前三个元素被初始化。根据C标准,其余的7个元素必须初始化为0。这也是您代码中发生的情况。正如xscott在他的回复中提到的那样,初始化列表中省略的所有内容都将被初始化为0。


0

值得注意的是,虽然内部大括号是可选的,但编译器会检查确保开括号只出现在应该出现的位置,并且没有嵌套项有太多的初始化程序。此外,一个可以省略结构体的一些字段,让编译器自动将它们清零,即使这个结构体不在数组的末尾。需要注意的是不同的实现在处理此问题的效率上可能会有所不同;有些实现会将初始化记录分成小块,而另一些则会在代码中插入大量的零。例如,如果每个结构体看起来像:

typedef struct {
  char name[8];
  char more_stuff[1016];
} THINGIE;
THINGIE my_array[] = {{"Fred"},{"George"},{"Mark"}};

一些编译器会生成3K大小的常量数据,而其他编译器则会生成三个相对较小的“const-init”记录。


编译器无法检查大括号是否只出现在它们“应该”出现的位置,因为它们可以在任何地方使用。即使这是有效的 C 代码:int x = {0}; - R.. GitHub STOP HELPING ICE
@R: True; 验证的方法是尝试将两个或更多的内容放入大括号中。我很确定 "int x = {0,1};" 是不合法的。 - supercat
@supercat:但那只是名字而已。外表常常会欺骗我们。 - user17492848

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