这在一定程度上取决于您放置相应变量定义的位置,而且似乎也取决于使用的编译器。
自动存储时间
让我们讨论一下变量具有自动存储持续时间时的区别(如果您将它放在函数或块范围内并且没有static
关键字):
void someFunction() {
variable_t my_variable; // (1)
variable_t my_variable = {}; // (2)
}
(1) 表示没有显式初始化的变量定义。根据这个在线 C 标准草案,它的价值是不确定的:
如果具有自动存储持续时间的对象未显式初始化,则其值是不确定的。
(2) 是一个变量定义,通过没有指示符的初始化器列表进行显式初始化,即不通过成员的名称将值与成员相关联,而仅通过值的顺序(参见6.7.9 p17..21)。
有趣的段落是6.7.9 p21,它指出如果初始化器列表的条目少于结构成员的数量,则根据静态存储持续时间的初始化规则对成员进行初始化(即 to0
或NULL
稍后解释):
如果大括号括起来的列表中的初始化程序少于聚合的元素或成员,...,则聚合的其余部分应隐式初始化,与具有静态存储持续时间的对象相同。
所以看起来如果你写了variable_t my_variable = {}
,那么所有的成员都被初始化为0
or NULL
。
但是,正如 aschepler 在评论中提到的,C 初始化列表语法规定初始化列表不能为空(参见cppreference.com):
...初始化程序必须是成员的初始化程序的非空、大括号括起来、逗号分隔的列表
因此,根据标准,C 中的初始化列表至少需要一个条目;在我的 XCode8.3 环境中使用 测试它时-std=gnu99
,似乎支持一个空的初始化列表,但我知道这不是一个有效的参考。所以为了安全而不依赖于特定的编译器扩展,你实际上应该写:
variable_t my_variable = {0};
静态存储时间
在文件范围内,您的变量定义将具有静态存储持续时间,然后适用其他规则(参见6.7.9 (10)):
(10) ... 如果具有静态或线程存储持续时间的对象未显式初始化,则:
- 如果是指针类型,则初始化为空指针;
- 如果它具有算术类型,则将其初始化为(正或无符号)零;
- 如果是聚合,则根据这些规则(递归)初始化每个成员,并将任何填充初始化为零位;
- 如果是联合,则根据这些规则(递归)初始化第一个命名成员,并将任何填充初始化为零位;
...
(21) 如果大括号括起来的列表中的初始值设定项少于聚合的元素或成员,...聚合的其余部分应被隐式初始化,与具有静态存储持续时间的对象相同。
所以如果你写...
#include <stdio.h>
variable_t my_variable; // (1)
variable_t my_variable = {}; // (2)
那么(1)和(2)实际上产生相同的结果,因为对于未显式初始化的变量(1),第(10)段适用,而对于显式但为空的初始化变量(2),根据第(21)段,每个member 回退到 (10) 的初始化规则。
同样,编译器可能不支持上面讨论的空初始化列表。
希望它有所帮助(因为它有很多打字:-))