说,我们有
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
分支,或者在值的情况下具有未指定或未定义的行为枚举不在列表中?
Since the switch above handles every possible listed value of the enum, is it allowed for the compiler to optimize away the default
branch above, or otherwise have an unspecified or undefined behavior in the case the value of enum is not in the list?
因为我期望 C 和 C++ 的行为应该相似,所以问题是关于这两种语言的.但是,如果 C 和 C++ 之间在这种情况下存在差异,那么了解它也会很高兴.
As I am expecting that the behavior should be similar for C and C++, the question is about both languages. However, if there's a difference between C and C++ for that case, it would be nice to know about it, too.
在 C++ 中,每个枚举都有一个底层的整数类型.如果明确指定(例如:enum test2 : long { a,b};
)或int
,则可以固定默认在 scoped 枚举的情况下(例如:enum class test { a,b };
):
In C++, each enum has an underlying integral type. It can be fixed, if it is explicitly specified (ex: enum test2 : long { a,b};
) or if it is int
by default in the case of a scoped enum (ex: enum class test { a,b };
):
[dcl.enum]/5: 每个枚举定义了一个不同于所有其他类型的类型.每个枚举还有一个底层类型.(...) 如果不显式指定的范围枚举类型的基础类型是整数.在这些情况下,底层类型被认为是固定的.
[dcl.enum]/5: Each enumeration defines a type that is different from all other types. Each enumeration also has an underlying type. (...) if not explicitly specified, the underlying type of a scoped enumeration type is int. In these cases, the underlying type is said to be fixed.
对于基础类型未明确固定的无作用域枚举(您的示例),该标准为您的编译器提供了更大的灵活性:
In the case of an unscoped enum where the underlying type was not explicitely fixed (your example), the standard gives more flexibility to your compiler:
[dcl.enum]/7: 对于底层类型不固定的枚举,底层类型是一个整数类型,可以表示所有的枚举中定义的枚举值.(...) 使用哪种整数类型作为底层是实现定义的type 除了基础类型不能大于 int除非枚举器的值不能放入 int 或 unsigned内部
[dcl.enum]/7: For an enumeration whose underlying type is not fixed, the underlying type is an integral type that can represent all the enumerator values defined in the enumeration. (...) It is implementation-defined which integral type is used as the underlying type except that the underlying type shall not be larger than int unless the value of an enumerator cannot fit in an int or unsigned int.
现在非常棘手的事情:枚举变量可以保存的值取决于基础类型是否固定:
Now a very tricky thing: the values that can be held by an enum variable depends on whether or not the underlying type is fixed:
如果它是固定的,"枚举的值就是基础类型.
否则,就是能容纳最小枚举数和最大枚举数的最小位域的最小值和最大值内的整数值.
otherwhise, it is the integral values within the minimum and the maximum of the smallest bit-field that can hold the smallest enumerator and the largest one.
您处于第二种情况,虽然您的代码可以在大多数编译器上运行,但最小的位域的大小为 1,因此您可以确定所有兼容 C++ 编译器的唯一值是 0 和 1 之间的值...
You are in the second case, although your code will work on most compilers, the smalest bitfield has a size of 1 and so the only values that you can for sure hold on all compliant C++ compilers are those between 0 and 1...
结论:如果要确保该值可以设置为 2,则必须使枚举成为作用域枚举,或者明确指示基础类型.**
Conclusion: If you want to ensure that the value can be set to 2, you either have to make your enum a scoped enum, or explicitly indicate an underlying type.**
更多阅读:
C 的情况要简单得多(C11):
The C situation is much simpler (C11):
6.2.5/16: 枚举包含一组命名的整数常量值.每个不同的枚举构成一个不同的枚举类型.
6.2.5/16: An enumeration comprises a set of named integer constant values. Each distinct enumeration constitutes a different enumerated type.
所以基本上,它是一个整数:
So basically, it is an int:
6.7.2.2./2 定义枚举常量值的表达式应为具有值的整数常量表达式可表示为 int.
6.7.2.2./2 The expression that defines the value of an enumeration constant shall be an integer constant expression that has a value representable as an int.
有以下限制:
每个枚举类型应与char兼容,一个有符号整数类型,或无符号整数类型.类型的选择是实现定义,但应能够表示枚举所有成员的值.
Each enumerated type shall be compatible with char, a signed integer type, or an unsigned integer type. The choice of type is implementation-defined, but shall be capable of representing the values of all the members of the enumeration.
这篇关于是否允许枚举具有未列出的值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!