首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何创建一个值超过max int的枚举?

如何创建一个值超过max int的枚举?
EN

Stack Overflow用户
提问于 2012-11-15 03:18:14
回答 5查看 3.4K关注 0票数 10

我在c++中创建一个枚举,以便使用二进制标志创建一个有限状态机。看起来是这样的:

代码语言:javascript
运行
复制
enum VStates
{
    NEUTRAL         =   0x00000000,     // 000000
    //  Physical Status
    DRY             =   0x00000001,     // 000001
    WET             =   0x00000002,     // 000010
    HOT             =   0x00000004,     // 000100
    COLD            =   0x00000008,     // 001000
    BURNED          =   0x00000016,     // etc..
    FROZEN          =   0x00000032,
    EROS            =   0x00000064,     // 
    THANATOS        =   0x00000128,     // 
    SLEEP           =   0x00000256,
    STUNNED         =   0x00000512,
    PARALYZED       =   0x00001024,
    POISONED        =   0x00002048,     //
    BLIND           =   0x00004096,
    SOFT            =   0x00008192,     // Flexible
    TOUGH           =   0x00016384,     // Resistent
    MAGNETIZED      =   0x00032768,
    POSSEDERUNT     =   0x00131072,     //
    // Mental Status
    ANGRY           =   0x00262144,
    DRUGGED         =   0x00524288, // Drugs Meaning
    HORNY           =   0x01048576, // Sexual Meaning
    // Material Status
    METAL           =   0x02097152,
    WOOD            =   0x04194304,
    GLASS           =   0x08388608,
    AIR             =   0x16777216,
    EARTH           =   0x33554432,
    DUST            =   0x67108864,
    LIGHT           =   0x134217728,
    SHADOW          =   0x268435456,
    WATER           =   0x536870912,
    // Total Status
    PROTECTED       =   0x1073741824,
    INVULNERABLE    =   0x2147483648

};

有些状态是不兼容的,所以我使用位运算符来管理它们。现在,我的编译器说:

代码语言:javascript
运行
复制
warning: integer constant is too large for 'long' type

这是声明此枚举的正确方式吗?我喜欢避免警告,那么我该如何解决这个问题呢?

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2012-11-15 03:26:35

(注意:为了使我的答案完整,我将添加一些我没有花时间注意到的东西,但其他人已经指出:您使用的是0x前缀,这意味着您的数字将被解释为十六进制。它们实际上不是2的幂,而且您的位标志测试也不会起作用!)

如果枚举像这样失控,就不要使用枚举类型。使用像std::bitset这样的东西。然后,您的枚举可以只是set...and中位位置的简单编号名称列表,您将不会以指数级耗尽枚举空间!

例如:

代码语言:javascript
运行
复制
enum VState {
    NEUTRAL,
    DRY,
    WET,
    COLD,
    BURNED,
    FROZEN,
    /* ... */
    VState_Max
};

bitset<VState_Max> state;

state[COLD] = true;
if (state[COLD]) {
    cout << "I am cold\n";
}

现在,您的枚举只是一个小的、可维护的数字,您不必担心是在64位平台或诸如此类的平台上。

我注意到您在原始示例中为空档指定了值"0“。如果您的意图是将其与其他things...such结合使用,使其能够成为state = NEUTRAL | INVULNERABLE | SHADOW并单独测试NEUTRAL,那么这在以前是行不通的。现在它会……你只需要把它放在枚举中,以便对位集进行索引。

但是如果它打算用作"nothing set“的名称,那么您应该从枚举中删除它,而不是使用以下命令测试no:

代码语言:javascript
运行
复制
if (state.none()) {
    // we are in the "NEUTRAL" state of nothing set...
}

...and如果你想把所有的位都设为false,你可以使用:

代码语言:javascript
运行
复制
state.reset();
票数 11
EN

Stack Overflow用户

发布于 2012-11-15 03:24:40

在C++11中,您可以指定枚举的基础类型。

代码语言:javascript
运行
复制
#include <cstdint>

enum VStates : uint64_t {
    // Values
}

顺便说一句,我建议不要计算出所有这些2的幂。您在计算中犯了一个错误,因为您编写了一个十六进制常量,但却给了它一个10进制数字的位数。但是,我不建议重新计算所有这些,而是推荐如下内容:

代码语言:javascript
运行
复制
#include <cstdint>

enum VStates : uint64_t {
    NEUTRAL = 0ULL,
    DRY = 1ULL << 0,
    WET = 1ULL << 1,
    HOT = 1ULL << 2,
    COLD = 1ULL << 3,
    // etc.
}

那你肯定不会犯错。ULL后缀确保文本被接受为至少64位宽的整数。

票数 13
EN

Stack Overflow用户

发布于 2012-11-15 03:26:00

枚举有31个非零值,因此它们都适合32位无符号值。问题是这里的值不是位值。将它们写成十进制值(从前面移除0x )或写成十六进制值(0x01、0x02、0x04、0x08、0x10、0x20、0x40等)。我个人不喜欢它,但是有些人写这种带移位的常量: 1<<0,1<<1,1<<2,1<<3,等等。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13385744

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档