此问题在此处已有答案:
What happens if you static_cast invalid value to enum class?(1个答案)
七年前就关门了。
说,我们有
enum E
{
Foo = 0,
Bar = 1
};
现在我们知道了
enum E v = ( enum E ) 2;
然后
switch ( v )
{
case Foo:
doFoo();
break;
case Bar:
doBar();
break;
default:
// Is the compiler required to honor this?
doOther();
break;
}
由于上面的开关处理枚举的每个可能列出的值,是否允许编译器优化掉上面的default
分支,或者在枚举的值不在列表中的情况下具有未指定或未定义的行为?
因为我期望C和C的行为应该是相似的,所以问题是关于这两种语言的。然而,如果C和C在这种情况下有区别,那么知道它也是很好的。
6条答案
按热度按时间rekjcdws1#
C++情况
在C++中,每个枚举都有一个基础整型。如果显式指定,它可以是 * fixed *(例如:
enum test2 : long { a,b};
),或者在scoped枚举的情况下默认为int
(例如:enum class test { a,b };
):在unscoped枚举的情况下,底层类型没有显式地固定(您的示例),该标准为您的编译器提供了更大的灵活性:
现在有一个非常棘手的问题枚举变量可以保存的值取决于底层类型是否是 * fixed *:
第二种情况是,虽然代码可以在大多数编译器上运行,但最小的位字段大小为1,因此在所有兼容的C++编译器上,您可以确定的值只有0到1之间的值......
更多阅读:
C情况
C的情况要简单得多(C11):
所以基本上,它是一个整型数:
具有以下限制:
每个枚举类型应与char、有符号整数类型或无符号整数类型兼容。类型的选择由实现定义,但应能够表示枚举的所有成员的值。
gt0wga4j2#
在C语言中,
enum
类型是一个整型类型,它足够大,可以容纳所有的enum
常量:(C11,6.7.2.2p4)“每个枚举类型应该与char、有符号整数类型或无符号整数类型兼容。类型的选择是实现定义的,110)但是应该能够表示枚举的所有成员的值”。
假设
enum E
的选定类型为_Bool
,_Bool
对象只能存储0
和1
,_Bool
对象存储不同于0
或1
的值而不调用未定义的行为是不可能的。在这种情况下,允许编译器假设
enum E
类型的对象在严格符合的程序中只能保存0
或1
,因此允许优化default
切换情况。5anewei63#
C++标准品7.2.7 [数据库枚举]:
有可能定义一个计数,其值未被任何计数器定义。
因此,您可以拥有未在枚举器列表中列出的枚举值。
但是在你的特定情况下,“底层类型”不是“固定的”(7.2.5).规范没有说明在这种情况下哪一个是底层类型,但它必须是整数.由于char是最小的这种类型,我们可以得出结论,还有其他的枚举值没有在枚举列表中指定.
顺便说一句,我认为编译器可以优化你的情况下,当它可以确定没有其他值被赋予v,这是安全的,但我认为没有编译器是聪明的。
mepcadol4#
此外,7.2/10:
算术型、枚举型的表达式可以显式转换为枚举型,如果在枚举型的枚举值范围内,则值不变;否则未指定结果枚举值。
wd2eg0qa5#
在C语言中,枚举器的类型为
int
,因此任何整数值都可以赋给枚举类型的对象。来自C标准(6.7.2.2枚举说明符)
3枚举数列表中的标识符被声明为类型为int的常量,并且可以出现在任何允许的地方。
在C中,枚举数具有定义它的枚举的类型。在C中,您应该显式地指定底层类型,或者编译器自己计算允许的最大值。
来自C++标准(7.2枚举声明)
5每个枚举定义一个不同于所有其他类型的类型。每个枚举也有一个基础类型。基础类型可以使用enum-base显式指定;如果没有显式指定,则作用域枚举类型的底层类型为int。2在这些情况下,底层类型被称为fixed。3在枚举说明符的右括号后面,**每个枚举数都有其枚举的类型。
因此在C语言中,枚举的任何可能值都是任何整数值。编译器可能不会优化删除默认标签的开关。
w51jfk4q6#
在C和C++中,这是可行的。
两者代码相同:
两者的输出相同:
在C中,
enum
是整型,所以你可以给它赋值而不用强制转换。在C++中,enum
是它自己的类型。