为什么{0}始终是有效的结构初始化程序?

问题描述

考虑以下C代码

typedef struct abc {
  int a[4];
  int b;
  int c;
} abc_t;

abc_t x = { 0 };

我发现用gcc -c -Wall -Wextra -pedantic -std=c99进行编译不会产生任何警告或错误消息。我的解释是0表示成员a的初始化程序。但是a一个数组,而不是标量。如果我将0替换为1,将立即产生预期的警告消息:

warning: missing braces around initializer [-Wmissing-braces]
   14 | abc_t x = { 1 };
      |           ^
      |             { }

C标准中是否有例外,{ 0 }始终被解释为将所有内容都设置为零的初始化程序? Common sources的文档似乎并未讨论该类型的明显不匹配(数组与标量)。

我知道初始化器不能为空,即{ }不是有效的初始化器。

解决方法

为什么{0}始终是有效的结构初始化程序?

因为语法允许它。允许省略括号以初始化子聚合。

C标准中是否有例外,{0}总是被解释为将所有内容都设置为零的初始化程序?

不,没有区别。文件范围内没有显式初始化的任何变量始终会初始化为零或指向NULL的指针。有关参考,请参见cppreference initialization

唯一的区别是警告和第一个数组元素的值存在。对于= {0},第一个数组元素将被显式初始化为零,其余的数组元素和其余的struct成员将被隐式初始化为零。

对于= {1},第一个数组元素将被显式初始化为一个。其余的数组元素和其余的struct成员都隐式初始化为零。糟糕,您的编译器也会发出警告,这是“实现质量”问题。

= {0}是一种常见的代码,程序员不在乎是否检查括号,因此,作为高质量编译器的编译器不想在这种情况下打扰他们忘记括号的程序员。如果您希望编译器在这种情况下发出警告,您就会知道答案-为编译器开发提供资金,创建功能请求和/或为社区做出贡献并实施类似-Wmissing-braces-also-when-zero的新警告。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...