我们都知道位域不是很便携,因此应该避免引用 C99 标准 6.7.2.1/10 -“结构和联合说明符”;
实现可以分配任何大到足以容纳位域的可寻址存储单元。如果有足够的空间剩余,紧跟在结构中另一个位域之后的位域将被打包到同一单元的相邻位中。如果剩余空间不足,则将不适合的位域放入下一个单元还是与相邻单元重叠是实现定义的。单元内位域的分配顺序(高位到低位或低位到高位)是实现定义的。未指定可寻址存储单元的对齐方式。
然而; 在处理硬件设备等时,通常必须处理特定的位布局,如果没有位域,这意味着讨厌和不可读(至少在我看来)位摆弄代码。
所以我想做的是使用位域,但是我想首先验证编译器生成的位域布局实际上符合我的期望。所以我正在做的是编写一些静态断言,在这种情况下,布局不匹配失败。
例如; 一个简单的大小断言;
struct bitField
{
bool AC : 1; // Accessed bit. Just set to 0. The CPU sets this to 1 when the segment is accessed.
bool RW : 1; // Readable bit/Writable bit. Is the code segment readable / data segment writeable.
bool DC : 1; // Direction bit/Conforming bit. 0=the segment grows up. 1=the segment grows down.
bool EX : 1; // Executable bit. If 1 code in this segment can be executed, ie. a code selector. If 0 it is a data selector.
bool DT : 1; // Descriptor type (Always 1?).
uint8_t DPL : 2; // Descriptor privilege level, 2 bits. - Contains the ring level, 0 = highest (kernel), 3 = lowest (user applications).
bool P : 1; // Present bit. - Is segment present? (1 = Yes). This must be 1 for all valid selectors.
};
static_assert(sizeof(bitField)==1, "Incorrect size of bitfield");
这很有魅力,并确保位域始终具有正确的大小,但是由于位域的实现特定性质,我不能假设位域内部的布局是否正确。所以我想做的是,静态断言位域的布局;
// Used to check that the bitfield, matches a specific required layout
union Bitfield_Layout_Checker
{
constexpr Bitfield_Layout_Checker(uint8_t raw) : raw(raw) {}
constexpr bitField getBitField()
{
return format;
}
uint8_t raw;
bitField format;
};
constexpr bool isBitfieldOkay()
{
return Bitfield_Layout_Checker(0x01).getBitField().P == true;
}
static_assert(isBitfieldOkay(), "Bitfield layout not okay");
所以这个测试,应该检查当前位是否在正确的位置。- 但是,当尝试编译上述代码时,使用 GCC v4.8.1 会产生此错误消息;
main.cpp:35:5: error: non-constant condition for static assertion
static_assert(isBitfieldOkay(), "Bitfield layout not okay");
^
main.cpp:35:34: in constexpr expansion of ‘isBitfieldOkay()’
main.cpp:32:58: in constexpr expansion of ‘Bitfield_Layout_Checker(1).Bitfield_Layout_Checker::getBitField()’
main.cpp:35:5: error: accessing ‘Bitfield_Layout_Checker::format’ member instead of initialized ‘Bitfield_Layout_Checker::raw’ member in constant expression
使用 Clang v3.1 会产生此错误消息;
a.cpp:35:19: error: static_assert expression is not an integral constant expression
static_assert(isBitfieldOkay(), "Bitfield layout not okay");
^~~~~~~~~~~~~~~~
a.cpp:23:20: note: read of member 'format' of union with active member 'raw' is not allowed in
a constant expression
return format;
^
a.cpp:23:20: note: in call to 'bitField(1.format)'
a.cpp:32:16: note: in call to ')'
return Bitfield_Layout_Checker(0x01).getBitField().P == true;
^
a.cpp:35:19: note: in call to 'isBitfieldOkay()'
static_assert(isBitfieldOkay(), "Bitfield layout not okay");
^
这表明我不允许读取联合的格式字段,当它通过原始字段初始化时。那么有什么办法可以解决这个问题吗?