如果你static_cast无效的值枚举类会发生什么?
考虑一下这个C ++ 11代码:
enum class Color : char { red = 0x1, yellow = 0x2 } // ... char *data = ReadFile(); Color color = static_cast<Color>(data[0]);
假设数据[0]实际上是100.什么是根据标准设置的颜色? 特别是,如果我稍后做
switch (color) { // ... red and yellow cases omitted default: // handle error break; }
标准保证默认会被打中吗? 如果没有,那么在这里检查错误的适当,最有效,最优雅的方法是什么?
编辑:
作为一个奖励,标准是否作出这方面的保证,但明确枚举?
根据标准设定的颜色是什么?
回答标准报价:
[expr.static.cast] / 10
整数或枚举types的值可以显式转换为枚举types。 如果原始值在枚举值(7.2)的范围内,则该值不变。 否则,结果值是未指定的(可能不在该范围内)。
我们来查看枚举值的范围 :[dcl.enum] / 7
对于基础types固定的枚举,枚举的值是基础types的值。
在CWG 1766之前因此,对于data[0] == 100
,指定结果值(*),并且不包含未定义行为(UB) 。 更一般地说,当你从底层types转换为枚举types时, data[0]
任何值都不会导致static_cast
UB。
CWG 1766之后请参阅CWG缺陷1766 。 [expr.static.cast] p10的段落已经被加强了,所以现在你可以调用UB,如果你把一个枚举types的enum的可表示范围以外的值。
(*) char
必须至less为8位宽,但不要求unsigned
。 C99标准的附录E要求最大可存储值至less为127
。
比较[expr] / 4
如果在expression式评估过程中,结果不是math定义的,或者不在其types的可表示值范围内,则行为是未定义的。
所以如果值足够大的话,这很容易导致UB,例如static_cast<Color>(10000);
。
现在, switch
语句:
[stmt.switch] / 2
条件应是整型,枚举型或types。 […] 积分促销活动。
[conv.prom / 4
基础types固定(7.2)的非范型枚举types的前值可以转换为其基础types的前值。 而且,如果可以对其基础types应用整体提升,则基础types固定的非范型枚举types的前值也可以被转换为提升的基础types的前值。
注意:范围枚举w / o enum-base的基础types是int
。 对于unscoped枚举,底层types是实现定义的,但不能大于int
如果int
可以包含所有枚举值的值。
对于一个无法枚举的枚举 ,这导致我们到/ 1
除了
bool
,char16_t
,char32_t
或wchar_t
其整数转换等级(4.13)小于int
的等级)的int
types的前值可以被转换为int
types的prvalue,如果int
可以表示源types的所有值; 否则,可以将源prvalue转换为unsigned int
types的prvalue。
在枚举枚举的情况下,我们将在这里处理int
。 对于范围枚举( enum class
和enum struct
),不适用整体升级。 不pipe怎样,积分提升也不会导致UB,因为存储值在基础types的范围内,并且在int
的范围内。
[stmt.switch] / 5
执行
switch
语句时,会评估其条件并与每个case常量进行比较。 如果其中一个case常量等于条件的值,则控制权将传递给匹配的case
标签之后的语句。 如果没有case
匹配的条件,并且如果有一个default
标签,控制权传递给default
标签标记的语句。
default
标签应该被打。
注意:可以再看看比较运算符,但是在引用的“比较”中没有明确地使用它。 事实上,在我们的例子中没有提到将UB引入范围或无限范围的枚举。
作为一个奖励,标准是否作出这方面的保证,但明确枚举?
enum
的范围是否在这里没有任何区别。 但是,底层types是否是固定的,是有区别的。 完整的[decl.enum] / 7是:
对于基础types固定的枚举,枚举的值是基础types的值。 否则,对于其中emin是最小枚举数并且e max是最大枚举的枚举,枚举的值是在范围b min到b max中的值 ,定义如下:对于二的补码表示设
K
为1
,0
表示补码或符号幅度表示。 b max是大于或等于max(| e min | –K
,| e max |)且等于2 M – 1的 最小值 ,其中M
是非负整数。 如果e min是非负的,那么b min是零,否则是(b max +K
) 。
幸运的是,你枚举的最小枚举符是red = 0x1
,所以max(| e min | – K
,| e max |)等于| e max | 在任何情况下,这是yellow = 0x2
。 对于正整数M
,大于或等于2
的最小值等于2 M -1 ,为3
( 2 2 -1 )。 (我认为目的是允许范围以1位的步长扩展 )。因此, b max是3
, bmin是0
。
因此, 100
会超出枚举的范围, static_cast
会产生一个未指定的值,这可能导致UB按照[expr] / 4。