管理 union 的未初始化字节的规则是什么? (假设一些已经初始化)
下面是一个 32 字节的 union ,我通过第一个成员只初始化了前 16 个字节。 似乎剩余的字节是零初始化的。这对我的用例来说很棒,但我想知道这背后的规则是什么 - 我期待垃圾。
#include <cstdint>
#include <iostream>
using namespace std;
union Blah {
struct {
int64_t a;
int64_t b;
};
int64_t c[4];
}
int main()
{
Blah b = {{ 1, 2 }}; // initialize first member, so only the first 16 bytes.
// prints 1, 2, 0, 0 -- not 1, 2, <garbage>, <garbage>
cout << b.c[0] << ", " << b.c[1] << ", " << b.c[2] << ", " << b.c[3] << '\n';
return 0;
}
我使用 -O3
-Wall
-Wextra
-pedantic
在 GCC 4.7.2 上编译(最后一个需要为匿名结构命名)。希望这能让我免于走运。
我也尝试过在堆栈上覆盖两个具有两个不同作用域的变量,但 gcc 没有给它们相同的地址。
我也尝试过用另一个结构替换数组,在那种情况下会很重要,但它没有改变任何东西。
我无法从这里访问在线编译器,它们被我的工作阻止了。
最佳答案
C11 标准 6.2.6.1.7 中最相关的部分,虽然没有专门针对初始化:
When a value is stored in a member of an object of union type, the bytes of the object representation that do not correspond to that member but do correspond to other members take unspecified values.
第 6.7.9.17 节说:
Each brace-enclosed initializer list has an associated current object. When no designations are present, subobjects of the current object are initialized in order according to the type of the current object: array elements in increasing subscript order, structure members in declaration order, and the first named member of a union.
但并没有明确地出来说其他位没有被初始化。对于静态 union ,6.7.9.10 说:
the first named member is initialized (recursively) according to these rules, and any padding is initialized to zero bits;
因此第一个命名成员和任何填充位将被零初始化,但与 union 的其他(暗示更大)成员对应的位将未指定。
所以你不能指望那些被初始化为零的额外字节。
请注意,从技术上讲,即使您确实将 c
数组初始化为零,当您在 struct
中存储内容时,那些多余的位将再次变得未指定,您可以'指望它们仍然为零。有很多代码假设这是真的(例如,将 char
数组放在 union 中以访问各个字节),实际上它可能是这样,但标准并不能保证
关于c++ - 联盟初始化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26793250/