在有符号基础类型枚举的位域上溢出
Overflow on bitfield for signed underlying type enum
这仅适用于C++11:
如果我有一个常规枚举,如下所示:
enum TestType
{
Test0 = 0,
Test1,
Test2,
Test3,
Test4,
Test5,
Test6,
Test7
}
以及像这样的打包结构:
struct
{
TestType a : 3
uint32_t b : 5
} TestStruct;
TestStruct.a
是否保证在访问时等于任何有效的分配枚举值? 或者编译器是否有可能分配有符号的基础类型,然后将位域a
视为范围 -4 到 3。
TestStruct.a
是否保证等于其分配的枚举值?
不。 默认初始化TestStruct
。 如果这是在全局空间中,那么它将初始化为零,a
和b
都将为 0。
如果这是在块空间中,则不会发生初始化,这意味着a
和b
具有未指定的值。 您只知道该值将在类型的可表示范围内。Test0
具有0
值在这里根本不起作用。
如果你有
TestStruct{};
然后a
和b
将为零,因为您正在初始化对象,在这种情况下,这意味着您将初始化它为零。 您也可以使用
TestStruct{value1, value2};
为a
和b
分配特定值。
对于a
是否可以存储TestType
的所有值的问题,我们必须查看 [class.bit]/4,其中指出
[...]如果枚举器的值存储到相同枚举类型的位字段中,并且位字段中的位数足以容纳该枚举类型 ([dcl.enum]( 的所有值,则原始枚举器值和位字段的值应相等。
强调我的
枚举的值由 [dcl.enum]/8 定义为
对于基础类型为固定的枚举,枚举的值是基础类型的值。否则,对于 emin是最小枚举器且 emax是最大枚举器的枚举,枚举的值是范围内的值 bmin到 bmax,定义如下:设 K 为 1 表示 2 的补码表示,
0
表示 1 的补码或符号幅度表示。b max 是大于或等于max(|emin− K, |emax|( 且等于 2M−1 的最小值,其中 M 是非负整数。如果 e min 为非负值,则 bmin为零,否则为 −(bmax+K(。如果 bmin为零,则足以容纳枚举类型的所有值的最小位字段的大小为 max(M,1(,否则为 M+1。可以定义具有任何枚举器未定义的值的枚举。如果枚举器列表为空,则枚举的值就像枚举具有值为 0 的单个枚举器一样
所以在这种情况下,e min 是 0,e max 7,所以 bmin是0,b max 等于或大于max(|emin| − K, |emax|( 即 7。因为如果我们使用 3 表示 M,它必须等于 2M−1,那么我们也得到 7。
我们有
如果 bmin为零,则足以容纳枚举类型的所有值的最小位字段的大小为 max(M,1(,否则为 M+1。
bmin为零,因此我们需要的最小位域是 3,因此您可以保证TestType
的所有值都适合a
.
- C++Union/Struct位域的实现和可移植性
- 具有位域的结构的 Constexpr 构造函数
- 如何解释 #if/#else 位域?(VC++菜鸟)
- 枚举位域和聚合初始化
- 在有符号基础类型枚举的位域上溢出
- 如何检查位域是否跨越所有位
- 访问位域联合是C++标准中常见的初始数据未定义行为
- 检测 32 位整数溢出
- 锈迹位域和枚举C++样式
- C/C++:uint8_t位域的行为不正确且不一致
- 如何将位域写入二进制文件
- 字节序和大小为 1 的位域
- 面向对象编程 - 位域私有结构的公共参考
- 使用位域的结构大小不正确
- 在 mingw 的 gcc-5.3 下具有混合位域和枚举递减的结构的意外大小
- 如何将位域成员的所有位设置为 1
- 带有 C++ 位域的匿名 typedef 的前向声明
- 通过套接字C++发送时,位域值会更改
- 有符号的 int 会中断较大位域的某些部分
- 位域.为什么没有输出