为什么我无法为c ++枚举类型变量分配正确的值?

时间:2013-11-07 11:48:53

标签: c++ enums padding memory-alignment

我无法理解那里发生了什么。 使用Visual Studio 2008,我已经定义了这样的枚举:

enum MyType{
    A,
    B,
    C
};

然后我用它来初始化一个成员变量:

class MyClass
{
    private:
        bool   bit_;
        uint16 num_;
        MyType member_;
    public:
        MyClass(MyType value){
            member_ = value; // This the assignment which fails
        } // Here, there's a breakpoint to query member_ value    
};

MyClass instance = new MyClass();

我正在使用Debug配置,所以在阅读时没有优化可以欺骗我 一个变量。在赋值后的断点处,debuger将member_的值显示为member_ = C

它可能是一个调试器问题刷新问题但是,在一个方法中,它在检查时评估为:

if(member_ == C){
    // ??
}

而且,分配给其他值会产生奇怪的数字,例如做member_ = B时,member_ = 258会给member_ = A。 你能告诉我什么是错的吗?提前谢谢。

编辑#1

我注意到一个有趣的效果,它解释了为什么在分配member_ == C之后,表达式true使用默认值评估枚举的enum MyType{ A, B, C}; // equivalent to enum MyType{ A = 0, B = 1, C = 2};

对于枚举

MyType  a = A; // but when fetching a the value is   2  (0x0002)  thats the map for C!
MyType  b = B; // but when fetching a the value is 258  (0x0102)
MyType  c = C; // but when fetching a the value is 514  (0x0202)

我得到了

enum MyType{ A = 5, B = 6, C = 7};

但是,如果我做

MyType  a = A; // but when fetching a the value is 1282  (0x0502)
MyType  b = B; // but when fetching a the value is 1538  (0x0602)
MyType  c = C; // but when fetching a the value is 1794  (0x0702)

我得到了

member_

因此,在分配#?!^%enum时,规则似乎是,移位8位并加2。 这听起来像编译器问题。

顺便说一句,将int的类型设为MyType而不是{{1}}并不会改变任何内容。

编辑#2 在该类中添加了两个成员,这是问题的真正原因。我会发布的 一旦时间限制消失(问题发布后8小时)就回答。

2 个答案:

答案 0 :(得分:1)

枚举条目不必具有唯一值。你可能有一个包含A,B,C的枚举,其中A和C都等于'42'。在这种情况下,当var的值为42时,IDE 将只显示一个匹配的条目A或C,而不是两者。

您可以轻松地创建包含“重复”条目的枚举,如下所示:

enum { A=1, B=1, C=1 }

但最有可能的是,你并没有这样做。但是,使用自动编号时,您可能会意外(或有意)创建重复项:

enum { A, B, C }       // 0,1,2
enum { A, B, C=0 }     // 0,1,0
enum { A=2, B=1, C }   // 2,1,2
enum { A=-1, B, C=0 }  // -1,0,0

请务必仔细检查您的枚举定义。

见ie http://www.learncpp.com/cpp-tutorial/45-enumerated-types/

答案 1 :(得分:1)

谢谢大家。 有人在工作时向我指出了问题的根源。

这是项目配置错误的问题, 这会产生数据对齐问题。

编译后,使用当前项目设置, 该类的两个第一个成员是3个字节的大小。

它应该是4个字节,因此1个字节的错位。 添加的额外2是未对齐字节的垃圾,所以, 整个效果是移动一个字节并添加2。

虽然增加了一个额外的成员,但这个效果被取消了 它不是一个优雅的解决方案(解决方案是配置 该项目核心)。

class MyClass
{
    private:
        bool   bit_;  // 1 byte
        uint16 num_;  // 2 byte

        bool dummy;   // extra byte to help the alignment

        MyType member_;
    public:
        MyClass(MyType value){
            member_ = value; // Now it works as expected.
        }
};