C++ 是否支持允许我们将对象及其所有填充字段初始化为零的语言构造。我在 cppreference.com 中发现了一些关于零初始化的令人鼓舞的措辞,表明在某些情况下,填充字节也将被清零。
引用自 cppreference.com: 零初始化
零初始化在以下情况下进行:
- 作为非类类型和没有构造函数的值初始化类类型的成员的值初始化序列的一部分,包括未提供初始化程序的聚合元素的值初始化。
零初始化的效果是:
- 如果 T 是标量类型,则对象的初始值是显式转换为 T 的整数常量零。
- 如果 T 是非联合类类型,则所有基类和非静态数据成员都初始化为零,并且所有填充都初始化为零位。构造函数(如果有)将被忽略。
- ...
人们会在value-initialization、aggregate-initialization和list-initialization中找到对零初始化的引用。
我使用相当最新的 GCC 和 clang C++ 编译器进行了测试,它们的行为似乎有所不同。
坦率地说,我努力解析这些规则,特别是考虑到不同的编译器行为,我无法弄清楚如何正确解释这些规则。
请参阅此处的代码(至少需要 C++11)。结果如下:
给出: Foo
struct Foo
{
char x;
int y;
char z;
};
Run Code Online (Sandbox Code Playgroud)
构造 | 克++ | 铿锵++ |
---|---|---|
富() | x:[----][0x42][0x43][0x44],v: 0 |
x:[----][----][----][----],v: 0 |
y:[----][----][----][----],v: 0 |
y:[----][----][----][----],v: 0 |
|
z:[----][0x4A][0x4B][0x4C],v: 0 |
z:[----][----][----][----],v: 0 |
|
富{} | x:[----][----][----][----],v: 0 |
x:[----][0x42][0x43][0x44],v: 0 |
y:[----][----][----][----],v: 0 |
y:[----][----][----][----],v: 0 |
|
z:[----][----][----][----],v: 0 |
z:[----][0x4A][0x4B][0x4C],v: 0 |
这里[----] …
假设我有以下结构:
typedef struct
{
unsigned field1 :1;
unsigned field2 :1;
unsigned field3 :1;
} mytype;
Run Code Online (Sandbox Code Playgroud)
前3位将可用,但sizeof(mytype)
将返回4
,这意味着29位填充.我的问题是,标准保证的这些填充位是否由语句初始化为零:
mytype testfields = {0};
Run Code Online (Sandbox Code Playgroud)
要么:
mytype myfields = {1, 1, 1};
Run Code Online (Sandbox Code Playgroud)
这样,memcmp()
假设位4..29为零,执行以下操作是安全的,因此不会影响比较:
if ( memcmp(&myfields, &testfields, sizeof(myfields)) == 0 )
printf("Fields have no bits set\n");
else
printf("Fields have bits set\n");
Run Code Online (Sandbox Code Playgroud) 我有一个结构,如
typedef struct
{
int a; // Let's say this ends up being 4 bytes
int b; // 4 bytes
char text[10]; // 10 bytes
} blah_t;
static blah_t myvar;
Run Code Online (Sandbox Code Playgroud)
blah_t
,但sizeof(blah_t)
由于填充而为20 个字节。myvar
是静态的,因此这将是零初始化。题:
memset(&myvar, 0, sizeof(blah_t))
任何memcmp
结构有效-即使是静态变量也是如此。calloc(1, sizeof(blah_t))
呢 字节19和20是否保证为零?我相信情况就是如此。