强制枚举值不正确?

时间:2011-10-06 15:40:30

标签: c++ enums

我在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的喉咙。如果这是依赖于实现的。

3 个答案:

答案 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)。