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 |
这里[----] …
我有一个预定义的结构(实际上是几个),其中变量跨越32位字边界.在Linux(以及使用GCC的Windows)中,我能够使用'attribute((packed))'将我的结构打包到正确的大小.但是我无法使用VC++和#pragma pack以相同的方式工作.
使用GCC,返回正确的6字节大小:
struct
{
unsigned int a : 3;
unsigned int b : 1;
unsigned int c : 15;
unsigned int troubleMaker : 16;
unsigned short padding : 13;
} __attribute__((packed)) s;
Run Code Online (Sandbox Code Playgroud)
使用VC++,这将返回不正确的8字节大小
#pragma pack(push)
#pragma pack(1)
struct
{
unsigned int a : 3;
unsigned int b : 1;
unsigned int c : 15;
unsigned int troubleMaker : 16;
unsigned short padding : 13;
} s;
#pragma pack(pop)
Run Code Online (Sandbox Code Playgroud)
我可以通过手动将"troubleMaker"分割成边界来实现工作,但我不愿意.有任何想法吗?
假设我有一段像这样的代码(并假设填充是按照我在评论中所说的插入的):
#include "stdint.h"
struct A
{
uint8_t x;
// 3 bytes of padding
uint32_t y;
};
void foo(struct A* a)
{
a->x = 0;
}
Run Code Online (Sandbox Code Playgroud)
是否允许编译器清除填充字节或对函数 foo 中的填充字节执行任何操作?
https://en.cppreference.com/w/c/language/object在这个问题上保持沉默,这让我相信编译器可以这样做......
我想知道编译器是否允许这样做的原因是我想要memcmp两个结构,并且我想知道我可以假设什么......