【问题标题】:How do bit fields interplay with bits padding in C++位域如何与 C++ 中的位填充相互作用
【发布时间】:2019-10-06 13:44:10
【问题描述】:
查看本题的C版here。
当有填充位时,我有两个关于位域的问题。
假设我有一个定义为的结构
struct T {
unsigned int x: 1;
unsigned int y: 1;
};
Struct T 只有两个实际使用的位。
问题 1:这两位是否总是底层 unsigned int 的最低有效位?还是依赖于平台?
问题 2:那些未使用的 30 位是否总是初始化为 0? C++ 标准对此有何规定?
【问题讨论】:
标签:
c++
language-lawyer
bit-fields
memory-layout
【解决方案1】:
问题 1:这两位是否总是底层 unsigned int 的最低有效位?还是依赖于平台?
非常依赖于平台。该标准甚至有一个注释只是为了澄清多少:
[class.bit]
1 ...类对象内的位域分配是
实现定义。位域的对齐是
实现定义。位域被打包成一些可寻址的
分配单位。 [ 注意:位域跨越分配单元在某些
机器,而不是其他人。位域从右到左分配
一些机器,在其他机器上从左到右。 — 尾注 ]
您不能对位域的对象布局做出太多假设。
问题2:那些未使用的30位总是初始化为0吗? C++ 标准对此有何规定?
您的示例有一个简单的聚合,因此我们可以枚举可能的初始化。不指定初始化器...
T t;
... 将default initialize 它,使成员具有不确定的价值。另一方面,如果您指定空括号...
T t{};
...对象将是aggregate initialized,因此位字段将使用{} 本身进行初始化,并设置为零。但这仅适用于聚合的成员,即位字段。没有指定填充位采用什么值(如果有)。所以我们不能假设它们会被初始化为零。
【解决方案2】:
Q1:通常从低到高(即 x 为 1
Q2:未使用位的值未定义。在某些编译器/平台上,堆栈初始化变量可能首先设置为零(可能!!),但不要指望它!堆分配的变量可以是任何东西,所以最好假设这些位是垃圾。使用隐藏在联合中的稍微不标准的匿名结构,您可以执行以下操作来确保位的值:
union T {
unsigned intval;
struct {
unsigned x : 1;
unsigned y : 1;
};
};
T foo;
foo.intval = 0;