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 |
这里[----] …
我知道memset对class初始化不满意.例如,类似以下内容:
class X { public:
X() { memset( this, 0, sizeof(*this) ) ; }
...
} ;
Run Code Online (Sandbox Code Playgroud)
vtbl如果virtual混合中有一个功能,它会破坏它.
我正在开发一个(巨大的)遗留代码库,它是C-ish但是用C++编译,因此所有成员都是POD,不需要传统的C++构造函数.C++的使用逐渐深入(比如虚函数),这就咬了开发人员没有意识到memset有这些额外的C++牙齿.
我想知道是否有一个C++安全的方法来进行初始的全部零初始化,然后可能会跟着特定的成员初始化,其中零初始化是不合适的?
我在C++中找到了用于初始化的类似问题memset,并使用memset将派生结构归零.这两个都有"不使用memset()"答案,但没有好的替代方案(特别是对于可能包含许多成员的大型结构).
我一直在寻找在C/C++中清空char数组的方法.我想出了这段代码:
char testName[20];
for(int i = 0; i < sizeof(testName); ++i)
{
testName[i] = (char)0;
}
Run Code Online (Sandbox Code Playgroud)
它已经工作了一段时间但是当我尝试strlen结果总是比键入的单词多两个.例如,我输入了dog输出为5 的单词.为什么会这样?我的char数组没有被清除吗?
这是我的代码:
char testName[20];
void loop()
{
if(Serial.available())
{
Serial.println("Waiting for name...");
index = 0;
for(int i = 0; i < sizeof(testName); ++i)
{
testName[i] = (char)0;
}
while(Serial.available())
{
char character = Serial.read();
testName[index] = character;
index++;
}
Serial.print("Name received: ");
Serial.println(testName);
Serial.print("The sentence entered is ");
Serial.print(strlen(testName));
Serial.println(" long");
delay(1000);
}
delay(1000);
}
Run Code Online (Sandbox Code Playgroud)
输出的屏幕截图:
输出为文本:
Name received: …Run Code Online (Sandbox Code Playgroud)