我想知道是否有人可以提供以下两段代码之间差异的详细,简单的解释。鉴于以下定义:
intellisense
有什么区别:
typedef struct {
stuff;
stuff_2;
} variable_t;
variable_t my_variable;
如果我执行第一个,然后从未完全初始化它,为什么编译器不会抛出错误?
注意:我正在使用variable_t my_variable = {};
进行编译,因此第二个是有效的,最终解决了我遇到的问题。我想知道为什么。
答案 0 :(得分:2)
它取决于你放置相应变量定义的位置,它似乎也取决于使用的编译器。
自动存储时间
让我们讨论当变量具有自动存储持续时间时的差异(如果将其置于函数或块范围内并且没有static
关键字,则会出现这种情况):
void someFunction() {
variable_t my_variable; // (1)
variable_t my_variable = {}; // (2)
}
(1)表示没有显式初始化的变量定义。根据这个online C standard draft,它的价值是不确定的:
如果未初始化具有自动存储持续时间的对象 显然,它的价值是不确定的。
(2)是一个变量定义,通过没有指示符的初始化列表显式初始化,即不通过名称将值与成员相关联,而只是通过值的顺序(参见6.7.9 p17..21)。
有趣的段落是6.7.9 p21,它指出如果初始化列表的条目数少于结构成员的数量,则根据静态存储持续时间的初始化规则初始化成员(即0
或NULL
,如后面所述):
如果括号括起的列表中的初始值设定项少于此值 是聚合的元素或成员,......,其余部分 aggregate应该与对象一样隐式初始化 有静态存储时间。
所以看来如果你写variable_t my_variable = {}
,那么所有成员都会被初始化为0
或NULL
。
但是,正如aschepler在评论中所提到的,C initialization list grammar指出初始化列表不能为空(参见cppreference.com):
...初始化程序必须是非空的,括号括起来的, 逗号分隔的成员初始值设定项列表
因此,根据标准,C中的初始化列表至少需要一个条目;在我的XCode8.3环境中使用-std=gnu99
进行测试时,似乎支持一个空的初始化列表,但我知道这不是一个有效的引用。因此,为了安全而不依赖于特定的编译器扩展,您应该写一下:
variable_t my_variable = {0};
静态存储时间
在文件范围内,您的变量定义将具有静态存储持续时间,然后应用其他规则(参见6.7.9 (10)):
(10)...如果具有静态或线程存储持续时间的对象是 没有明确初始化,那么:
- 如果它有指针类型,则将其初始化为空指针;
- 如果它有算术类型,则初始化为(正数或无符号)零;
- 如果是聚合,则根据这些规则初始化(递归)每个成员,并将任何填充初始化为零位;
- 如果是联合,则根据这些规则初始化(递归)第一个命名成员,并初始化任何填充 为零位;
...
(21)如果括号括起的列表中的初始值设定项少于聚合的元素或成员,则聚合的其余部分应与具有静态存储持续时间的对象隐式初始化。 / p>
所以,如果你写...
#include <stdio.h>
variable_t my_variable; // (1)
variable_t my_variable = {}; // (2)
然后(1)和(2)实际产生相同的结果,因为对于未明确初始化的变量(1),段落(10)适用,并且对于明确但空的初始化变量(2),根据段落(21) ),每个成员都回到(10)的初始化规则。
同样,编译器可能不支持如上所述的空的初始化列表。
希望它有所帮助(因为它打字很多:-))
答案 1 :(得分:-2)
宣布:
variable_t my_variable; // a variable_t that is uninitialized
variable_t my_variable = {}; // a variable_t initialized with zeroes.
请注意,对于在文件范围内声明的变量,这并不重要,因为数据是 - 在程序启动之前通常归零。
在堆栈上使用,第二行有效地用零填充my_variables。就像打电话给:
一样 memset(&variable, 0, sizeof(variable));
这是有效的,因为在C中,您可以使用struct
复制=
。
这是计算机肯定会赢的小游戏。
struct A { /*...*/ };
void main()
{
A a; // random
A b = {};
if (memcmp(&a, &b, sizeof(A)) == 0)
{
printf("You win\n");
return;
}
a = b;
if (memcmp(&a, &b, sizeof(A)) == 0)
{
printf("I win\n");
}
}