将全零分配给 C 中的嵌套结构(GCC 版本 < 5)

Assignment of all-zeroes to a nested struct in C (GCC versions < 5)

我在 C99 中有一个嵌套结构(我在 -std=gnu99 -Wall 中使用 GCC 4.8.3)。

struct X
{
  struct
  {
    int p;
    int q;
  }
  a;

  struct
  {
    int m;
    int n;
  }
  b;

  int c, d, e;
};

我想为它定义一个全零的"default value"。一种方法是明确指定每个字段的值,但我想使用快捷方式 { 0 } 作为默认值。这被称为 "universal zero-initializer" - 将其分配给一个变量将使该变量的所有字段归零。

但是,如果我尝试这样做:

struct X x = { 0 };

我得到 warning: missing braces around initializer,然后是关于缺少 X 字段初始值设定项的进一步警告。

一般来说,归零 x 不是问题。我知道其他选项,例如 memset() 和使用静态变量自动初始化为全零。这个问题是关于通用零初始化器,以及它为什么会意外生成警告。

为什么上面的操作看起来应该没问题,但会产生警告?

怎么样:

#define DEFAULT_VALUE 0
#define DEFAULT(value, target) memset(&target, value, sizeof target)
#define DEFAULT_ZERO(target) DEFAULT(DEFAULT_VALUE, target)

struct A a;
DEFAULT_ZERO(a);

我们试图在这里做到真正通用,但是,我认为默认值永远不会改变。 memset 函数对结构中的字段一无所知。 memset 仅将一个字节(无符号字符)复制到指向的字符串的前 n 个字节(&target)。所以,我认为我们将结构的所有字节设置为不同于 0.

的值是没有意义的

首先,memset{0} 实现了不同的目标。在这种情况下,memset 会将 struct 的每个 byte 设置为 0,因此包括填充字节,因为 sizeof 会将它们包括为嗯。
{0} 会将每个 成员 初始化为 0,因为您没有初始化每个成员,因此其余成员将自动初始化为零。此行为完全有效且符合标准 C.

如果 gcc too restrictive about that, consider adding -Wno-missing-initializer although GCC 5.1 seems 已经放弃了。

(我将根据我从其他人的贡献中学到的知识自己回答这个问题。)

简答

简而言之,这是一个由 5.1 版修复的 GCC 错误:

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53119

早期版本的解决方法

分配给非嵌套结构(仅包含内置类型的结构)时不会出现此问题。因此,一个可用的解决方法是对 GCC 4.8.3 中有效且没有警告的父结构的任何字段进行赋值。根据标准,剩余的字段将被清零。例如:

struct X x = { .a = { 0 } };

另见 Why is the compiler throwing this warning: "missing initializer"? Isn't the structure initialized?

对每个结构级别使用 {0}

struct X {
  struct {
    int p;
    int q;
  } a;

  struct {
    int m;
    int n;
  } b;

  int c, d, e;
};

// struct X x = { 0 };
struct X x = { { 0 }, { 0 }, 0 };

我现在看到这与 "GCC versions < 5" 有关。这种方法用 "4.9.2"

进行了测试