我在C++的枚举中遇到了一些不寻常的(至少对我而言)行为.我在Visual Studio 2008和g ++版本4.4.3中尝试了以下内容
#include <iostream>
using namespace std;
enum testEnum
{
// no zero enum
one = 1,
two = 2,
three = 3
};
int main(int argc, char *argv[])
{
testEnum e; // undefined value (may be zero, but thats just luck)
cout << "Uninitialized enum e = " << e << endl;
/*
testEnum e2(0); // error converting from int to enum
*/
testEnum e3(testEnum(0)); // forces zero !?!!?!?
cout << "zero enum e3 = " << e3 << endl; // prints '0'
testEnum e4(testEnum(9999)); // forces 9999 ?!?!?!?!
cout << "9999 enum e4 = " << e4 << endl; // prints '9999'
return 0;
}
Run Code Online (Sandbox Code Playgroud)
e的未定义值是我所期望的,我理解为什么你不能从int转换为枚举(但你可以转向另一种方式).
我很好奇最后两个枚举(e3和e4)如何被允许编译并获得你想要给它们的任何值.
另外,我发现这个:
testEnum e();
Run Code Online (Sandbox Code Playgroud)
在studio和linux中编译,在linux中进行cout-ing产生'1',但在工作室中我遇到了一个链接器错误:
main.obj : error LNK2001: unresolved external symbol "enum testEnum __cdecl e2(void)"
Run Code Online (Sandbox Code Playgroud)
在工作室,我可以这样做:
testEnum e = testEnum();
Run Code Online (Sandbox Code Playgroud)
但是,它的结果是'0'而不是'1'
所以我的主要问题是如何在上面的例子中像e3和e4一样将任何值压缩到枚举的喉咙上.如果这取决于实现是否依赖.
枚举保证在其最小定义值和最大定义值之间的范围内保持任何值,并且未指定它如何处理该范围之外的数字.
§7.2/ 3
...如果没有明确指定,则作用域枚举类型的基础类型是int."§7.2/ 7
...对于枚举,其中emin是最小的枚举数且emax是最大的,枚举的值是bmin到bmax范围内的值,定义如下:令两个补码表示为K为1 0表示一个补码或符号幅度表示.bmax是大于或等于max(| emin | - K,| emax |)且等于2M-1的最小值,其中M是非负整数.如果emin是非负的,则bmin为零,否则为 - (bmax + K).如果bmin为零,则大小足以容纳枚举类型的所有值的最小位字段的大小为max(M,1),否则为M + 1.§7.2/ 10
算术或枚举类型的表达式可以显式转换为枚举类型.如果它在枚举类型的枚举值范围内,则该值不变; 否则生成的枚举值未指定.
另请注意,testEnum e();声明一个返回a的函数.testEnum 这是由最令人烦恼的解析引起的.不知道为什么GCC决定等于一个(也许它被强制转换为指针 - >某种方式的bool?) testEnum e = testEnum();是一个默认初始化a的有效语句testEnum,对于基元(显然enums)意味着将它们设置为零.
请注意,这并不意味着枚举可能不会超出其定义的范围; 如N4296脚注96所述:
这组值用于定义枚举类型的提升和转换语义.它不排除枚举类型的表达式具有超出此范围的值.
我还要提一下,在C++ 03中制作类型安全的枚举并不是特别复杂,只有一些奇怪的技巧. http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Type_Safe_Enum显示了一种方式.