[英]Are unmentioned struct fields *always* initialised to zero (i.e. when the struct is on the stack)?
From experimentation (in Clang and GCC, with -O2 and -O0) is seems that in the following code 来自实验(在Clang和GCC中,使用-O2和-O0) 似乎在以下代码中
typedef struct foo_s { int i; int j; } foo_t;
int main(void) {
foo_t foo = {.i = 42};
...
foo.j is automatically zero. foo.j自动为零。
Is the guaranteed by C99 onwards, or is it a compiler specific implementation detail? 是否由C99开始保证,还是编译器特定的实现细节?
Note: I've even tried writing 0xFFs to invalid memory below the stack, at the address which foo is later given. 注意:我甚至尝试将0xFF写入堆栈下方的无效内存,稍后给出foo的地址。
Update: There are a couple of comments stating that this is just because the memory below the stack happens to contain zeros. 更新:有几条评论声明这只是因为堆栈下方的内存恰好包含零。 The following code makes sure this is not the case, and may prove that GCC -O0 is zeroing memory.
以下代码确保不是这种情况,并且可能证明GCC -O0正在归零内存。
The offsets of -7 and -6 are compiler dependent. -7和-6的偏移量取决于编译器。 They needed to be different in Clang.
他们需要在Clang中有所不同。
typedef struct foo_s { int i; int j; } foo_t;
int main(void) {
int r;
int *badstack0 = &r - 7;
int *badstack1 = &r - 6;
*badstack0 = 0xFF; // write to invalid ram, below stack
printf("badstack0 %p, val: %2X\n", badstack0, *badstack0);
*badstack1 = 0xEE; // write to invalid ram, below stack
printf("badstack1 %p, val: %2X\n", badstack1, *badstack1);
// struct test
foo_t foo = {.i = 42};
printf("&foo.i %p\n", &foo.i);
printf("&foo.j %p\n", &foo.j);
printf("struct test: i:%i j:%i\n", foo.i, foo.j);
return 0;
}
Output: 输出:
badstack0 0x7fff221e2e80, val: FF
badstack1 0x7fff221e2e84, val: EE
&foo.i 0x7fff221e2e80
&foo.j 0x7fff221e2e84
struct test: i:42 j:0
If you provide any initialisers, the members not explicitly mentioned are initialised as if they were static. 如果您提供任何初始化程序,则未明确提及的成员将被初始化为好像它们是静态的。 That's guaranteed by the standard in 6.7.9 (19):
这是由6.7.9(19)中的标准保证的:
The initialization shall occur in initializer list order, each initializer provided for a particular subobject overriding any previously listed initializer for the same subobject;
初始化应在初始化器列表顺序中进行,每个初始化器为特定子对象提供,覆盖同一子对象的任何先前列出的初始化器; all subobjects that are not initialized explicitly shall be initialized implicitly the same as objects that have static storage duration .
未明确初始化的所有子对象应与具有静态存储持续时间的对象隐式初始化 。
(Emphasis added by me) (我强调的重点)
If you don't initialise any member, the values of all members are indeterminate. 如果您没有初始化任何成员,则所有成员的值都是不确定的。
C guarantees that as long as at least one member of an array/struct/union* is initialized explictily, then all other members will be initialized as if they had static storage duration, as cited in Daniel Fischer's answer. C保证只要数组/结构/联合*的至少一个成员被明确初始化,那么所有其他成员将被初始化,就好像它们具有静态存储持续时间一样,如Daniel Fischer的答案所述。 In other words, all the other members are set to zero or NULL automatically.
换句话说,所有其他成员自动设置为零或NULL。
The storage type of the array/struct/union matters not, they are initialized according to the same rule no matter if they have automatic or static storage duration. 数组/结构/联合的存储类型不重要,它们根据相同的规则初始化,无论它们是否具有自动或静态存储持续时间。
This is not something unique to C99 or later, C has always had this requirement. 这不是C99或更高版本所特有的,C 总是有此要求。 All conforming C compilers follow this rule, it is normative and not implementation-defined.
所有符合C的编译器都遵循此规则,它是规范性的,而不是实现定义的。
This has nothing to do with "debug release" zero outs. 这与“调试版本”零出局无关。
As a matter of fact, this rule is the explanation why you can zero a whole array by writing 事实上,这个规则解释了为什么你可以通过写作将整个数组归零
int array[100] = {0}
. int array[100] = {0}
。
This code means, "initialize the first element to zero, and initialize the 99 remaining ones as if they had static storage duration, ie make them zero too". 此代码表示“将第一个元素初始化为零,并将剩余的99个元素初始化为好像它们具有静态存储持续时间,即使它们也为零”。
(*) Those three types are formally named "aggregate type" in the C standard. (*)这三种类型在C标准中正式命名为“聚合类型”。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.