如果枚举不能适合无符号整数类型会发生什么?

Sim*_*mer 45 c++ enums types language-lawyer

按照芭丝谢芭的要求,并作为一个后续问题"如果一个枚举不适合整体类型会怎样?" :

假设枚举定义如下:

enum foo : unsigned int
{
    bar = UINT_MAX,
    oops
};
Run Code Online (Sandbox Code Playgroud)

oops定义的价值还是不是?


MSVS2015编译:

warning C4340: 'oops': value wrapped from positive to negative value
warning C4309: 'initializing': truncation of constant value
warning C4369: 'oops':  enumerator value '4294967296' cannot be represented as 'unsigned int', value is '0'
Run Code Online (Sandbox Code Playgroud)

MSVS2015输出:

bar = 4294967295
oops= 0
Run Code Online (Sandbox Code Playgroud)

gcc 4.9.2编译:

9 : note: in expansion of macro 'UINT_MAX'
bar = UINT_MAX,
^
10 : error: enumerator value 4294967296l is outside the range of underlying type 'unsigned int'
oops
^
Compilation failed
Run Code Online (Sandbox Code Playgroud)

gcc 4.9.2输出

//compilation failed
Run Code Online (Sandbox Code Playgroud)

Shm*_* H. 19

这是一个非常有趣的问题.简单的答案是,这实际上是未定义的:标准没有说明这种情况.

为了有一个更好的例子,考虑一下enum:

 enum foo : bool { True=true, undefined };
Run Code Online (Sandbox Code Playgroud)

根据标准:

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

因此,foo::undefined我们的例子中的值是2(true+1).哪个不能表示为bool.

它是不是形成了?

,根据标准,它是完全有效的,只有未固定的基础类型具有不能代表所有枚举器值的限制:

[ dcl.enum ]/7:对于其基础类型未修复的枚举,[...]如果没有整数类型可以表示所有枚举器值,则枚举是格式错误的.

它没有说明不能代表所有枚举器值的固定底层类型.

什么是原来的问题的价值oopsundefined

它是未定义的:标准没有说明这种情况.

可能的值foo::undefined:

  • 最高可能值(true):undefined并且oops应该是基础类型的最大值.
  • 最低可能值(false):基础类型的最小值.注意:在有符号整数中,它与Integer溢出(未定义行为)的当前行为不匹配.
  • 随机值(?):编译器将选择一个值.

所有这些值的问题在于它可能导致两个具有相同值的字段(例如foo::True == foo::undefined).

初始化程序(例如undefined=2)和"隐式"初始化程序(例如True=true, undefined)之间的区别

根据标准:

[ dcl.enum ]/5:如果底层类型是固定的,闭括号之前,每个枚举的类型是基础类型常数表达式枚举定义应为基础类型的一个转换后的常量表达式.

换一种说法:

 enum bar : bool { undefined=2 };
Run Code Online (Sandbox Code Playgroud)

相当于

 enum bar : bool { undefined=static_cast<bool>(2) };
Run Code Online (Sandbox Code Playgroud)

然后bar::undefinedtrue.在"隐式"初始化器中,情况并非如此:这个标准段落只说初始化器,而不是"隐式"初始化器.

摘要

  1. 通过这种方式,enum具有固定基础类型的可能具有不可表示的值.
  2. 它们的价值未被标准定义.

根据问题和评论,这在GCC和clang中无效,但对MSVS-2015有效(带警告).