我在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;
}
e的未定义值是我所期望的,我理解为什么你不能从int转换为枚举(但你可以采用另一种方式)。
我很好奇最后两个枚举(e3和e4)如何被允许编译并获得你想要给它们的任何值。
另外,我发现了这个:
testEnum e();
在工作室和linux中编译,在linux中cout-ing产生'1',但在工作室中我遇到了链接器错误:
main.obj : error LNK2001: unresolved external symbol "enum testEnum __cdecl e2(void)"
在工作室,我可以这样做:
testEnum e = testEnum();
但是,结果它产生了'0'而不是'1'
所以我的主要问题是如何在上面的例子中像e3和e4一样将任何值压缩到enum的喉咙。如果这是依赖于实现的。
答案 0 :(得分:8)
C ++枚举不是类型安全的。正如你所说的那样,你可以将任何一个值压低到枚举喉咙。此功能不依赖于实现,它已在标准中得到体现。
C ++ 11引入了strongly-typed enumerations,它们使用不同的语法声明,以免破坏旧代码的类型不安全枚举。
答案 1 :(得分:8)
枚举保证可以保持其最小定义值与其最大值之间的任何值,并且未指定它如何处理该范围之外的数字。
§7.2/ 3
...如果没有明确指定,则为a的基础类型 范围枚举类型是int。“7.2 / 7
...对于枚举,其中emin是最小的枚举数和emax 是最大的,枚举的值是中的值 范围bmin到bmax,定义如下:设K为1表示两个 补码表示和0表示一个补码或 符号幅度表示。 bmax是大于的最小值 或者等于max(| emin | - K,| emax |)并且等于2M - 1,其中M是a 非负整数。如果emin是非负的,则bmin为零,并且 - (bmax + K)否则。最小位域的大小足够大 如果bmin为,则保持枚举类型的所有值为max(M,1) 否则为零和M + 1。§7.2/ 10
算术或枚举类型的表达式可以转换为 枚举类型显式。如果它在,则值不变 枚举类型的枚举值范围;否则 结果枚举值未指定。
另请注意,testEnum e();
声明了一个返回testEnum
的函数。这是由Most Vexing Parse引起的。不确定为什么GCC决定等于一个(也许它被强制转换为指针 - >某个&gt; bool?)testEnum e = testEnum();
是一个有效的语句,默认初始化testEnum
,对于基元(显然{ {1}})表示将它们设置为零。
请注意,这并不意味着枚举可能不会超出其定义的范围;如N4296的脚注96所述:
这组值用于定义枚举类型的提升和转换语义。它并不排除 枚举类型的表达式,其值超出此范围。
我还应该提一下,在C ++ 03中制作类型安全的枚举并不是特别复杂,只有一些奇怪的技巧。 http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Type_Safe_Enum显示了一种方式。
答案 2 :(得分:0)
枚举它只是一个内存,通常它被实现为int,而编译器应该强制你只为它们分配正确的值。但是没有编译器是完美的..你提出的那些案例不应该是有效的(undef)。