在有符号基础类型枚举的位域上溢出

Overflow on bitfield for signed underlying type enum

本文关键字:位域 溢出 枚举 类型 符号      更新时间:2023-10-16

这仅适用于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。 如果这是在全局空间中,那么它将初始化为零,ab都将为 0。

如果这是在块空间中,则不会发生初始化,这意味着ab具有未指定的值。 您只知道该值将在类型的可表示范围内。Test0具有0值在这里根本不起作用。

如果你有

TestStruct{};

然后ab将为零,因为您正在初始化对象,在这种情况下,这意味着您将初始化它为零。 您也可以使用

TestStruct{value1, value2};

ab分配特定值。


对于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,所以 bmin0,b max 等于或大于max(|emin| − K, |emax|( 即 7。因为如果我们使用 3 表示 M,它必须等于 2M−1,那么我们也得到 7。

我们有

如果 bmin为零,则足以容纳枚举类型的所有值的最小位字段的大小为 max(M,1(,否则为 M+1。

bmin为零,因此我们需要的最小位域是 3,因此您可以保证TestType的所有值都适合a.