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

时间:2016-09-21 15:44:41

标签: c++ types enums language-lawyer

根据Bathsheba的要求以及对"What happens if an enum cannot fit into an integral type?"的跟进问题:

假设枚举定义如下:

enum foo : unsigned int
{
    bar = UINT_MAX,
    oops
};

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'

MSVS2015输出:

bar = 4294967295
oops= 0

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

gcc 4.9.2输出

//compilation failed

1 个答案:

答案 0 :(得分:19)

这是一个非常有趣的问题。简单的答案是,这实际上是未定义的:标准对此案例没有任何说明。

要想有一个更好的例子,请考虑这个enum

 enum foo : bool { True=true, undefined };

根据标准:

  

[ dcl.enum ] / 2 :[...]没有初始化程序的枚举器定义 枚举器提供通过将上一个枚举器的值增加一个而获得的值。

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

形成不良吗?

,根据标准,它完全有效,只有未修复的基础类型具有无法表示所有枚举器值的限制:

  

[ dcl.enum ] / 7 :对于其基础类型未修复的枚举,[...]如果没有整数类型可以表示所有枚举器值,列举是不正确的。

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

原始问题&{39} oopsundefined的价值是多少?

未定义:标准对此案例没有任何说明。

foo::undefined的可能值:

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

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

初始值设定项(例如undefined=2)和"隐式"之间的区别初始值设定项(例如True=true, undefined

根据标准:

  

[ dcl.enum ] / 5 :如果基础类型是固定的,那么在右括号之前的每个枚举器的类型是基础类型< / em>和枚举器定义中的常量表达式应该是基础类型的转换常量表达式。

换句话说:

 enum bar : bool { undefined=2 };

相当于

 enum bar : bool { undefined=static_cast<bool>(2) };

然后bar::undefined将是true。在一个&#34;隐含的&#34;初始化程序,情况并非如此:这个标准段落只说初始化程序,而不是关于&#34;隐含&#34;初始化程序。

摘要

  1. 通过这种方式,具有 fixed-underlying-type enum可能具有不可表示的值。
  2. 标准未定义它们的价值。
  3. 根据问题和评论,这在GCC和clang中无效,但对MSVS-2015有效(带警告)。