对大枚举值的表示有什么保证吗?

Bat*_*eba 28 c c++ enums

假设我(在32位机器上)

enum foo {
    val1 = 0x7FFFFFFF, // originally '2^31 - 1'
    val2,
    val3 = 0xFFFFFFFF, // originally '2^32 - 1'
    val4,
    val5
};
Run Code Online (Sandbox Code Playgroud)

val2,val4和val5的值是多少?我知道我可以测试它,但结果是标准化的吗?

md5*_*md5 16

在C标准中:

C11(n1570),§6.7.2.2枚举说明符

每个枚举类型应与char有符号整数类型或无符号整数类型兼容.类型的选择是实现定义的,但应能够表示枚举的所有成员的值.

如果编译器使用的基础类型无法表示这些值,则行为未定义.

C11(n1570),§4.一致性

如果违反约束或运行时约束之外的''shall''或''shall not''要求,则行为未定义.

  • @Dyp,是的,所以编译器可以选择它.但是,如果您执行"0xFFFFFFFFFFFFFFFFllu",那么如果编译器不支持大于64位的整数,那么它将是未定义的行为. (3认同)

Arn*_*rtz 10

从C++ 11标准(§7.2,6,强调我的):

对于其基础类型未修复的枚举,基础类型是一个整数类型,可以表示枚举中定义的所有枚举器值.如果没有整数类型可以表示所有枚举器值,则枚举是不正确的.它是实现定义的,其中整数类型用作底层类型,除了底层类型不应大于int,除非枚举器的值不能适合int或unsigned int.

因此,如果存在大于32位的整数类型,编译器将很乐意做正确的事情.如果没有,枚举就会变形.没有环绕.

值将是:

enum foo {
    val1 =                       0x7FFFFFFF, 
    val2,              //        0x80000000   = 2^31
    val3 =                       0xFFFFFFFF, 
    val4,              //0x0000000100000000   = 2^32
    val5               //0x0000000100000001   = 2^32+1
};
Run Code Online (Sandbox Code Playgroud)

越来越多的数字也得到了很好的定义(§7.2,2):

[...]没有初始值设定项的枚举器定义为枚举数提供了通过将前一个枚举数的值增加1而获得的值.


dyp*_*dyp 5

C99 / C11

序幕:

5.2.4.2.1需要int至少16个位宽; AFAIK 没有上限(但long必须大于或等于 6.2.5 /8)。

6.5 /5:

如果在对表达式求值期间出现异常情况(即,如果结果未在数学上定义或不在其类型的可表示值范围内),则行为未定义。


如果你的 `int` 是 32 位宽(或更少)

那么 OP 中的示例违反了约束 6.7.2.2 /2

定义枚举常量值的表达式应为整数常量表达式,其值可表示为int.

此外,统计员被定义为类型的常数int6.7.2.2 / 3

枚举器列表中的标识符被声明为具有类型的常量,int并且可以出现在任何允许的地方。


注意,还有的之间的差异枚举类型枚举/枚举常量的类型

enum foo { val0 };
enum foo myVariable;        // myVariable has the type of the enumeration
uint_least8_t v = val0*'c'; // if val0 appears in any expression, it has type int
Run Code Online (Sandbox Code Playgroud)


在我看来,这允许缩小,例如将枚举类型的大小减少到 8 位:

enum foo { val1 = 1, val2 = 5 };
enum foo myVariable = val1;    // allowed to be 8-bit
Run Code Online (Sandbox Code Playgroud)

但它似乎不允许扩大,例如

enum foo { val1 = INT_MAX+1 }; // constraint violation AND undefined behaviour
// not sure about the following, we're already in UB-land
enum foo myVariable = val1;    // maximum value of an enumerator still is INT_MAX
                               // therefore myVariable will have sizeof int
Run Code Online (Sandbox Code Playgroud)

枚举器的自动递增

由于 6.7.2.2 /3,

[...] 每个后续枚举器都=将其枚举常量定义为通过将前一个枚举常量的值加 1 获得常量表达式的值。[...]

该示例导致 UB:

enum foo {
    val0 = INT_MAX,
    val1            // equivalent to `val1 = INT_MAX+1`
};
Run Code Online (Sandbox Code Playgroud)