如何使枚举的值超过允许的最大整数? 我用C++制作了一个枚举,用二进制标志来制作一个有限状态机。它看起来像: 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 };

如何使枚举的值超过允许的最大整数? 我用C++制作了一个枚举,用二进制标志来制作一个有限状态机。它看起来像: 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 };,c++,variables,enums,C++,Variables,Enums,有些状态是不兼容的,所以我使用位运算符来管理它们。现在,我的编译器说: warning: integer constant is too large for 'long' type 这是声明此枚举的正确方法吗?我喜欢避免警告,因此,如何解决此问题?使用较小的数字。枚举只能与长枚举一样大。long的大小取决于编译器,但典型的大小是32位或64位。我在那里看到一些10位的十六进制数,它们太大了。如果您使用的是C++11,您可以声明一个强类型枚举,定义类型为unsigned long(\u int6

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

warning: integer constant is too large for 'long' type

这是声明此枚举的正确方法吗?我喜欢避免警告,因此,如何解决此问题?

使用较小的数字。枚举只能与长枚举一样大。long的大小取决于编译器,但典型的大小是32位或64位。我在那里看到一些10位的十六进制数,它们太大了。

如果您使用的是C++11,您可以声明一个强类型枚举,定义类型为
unsigned long
\u int64
在Windows中,尽管您可能应该使用可移植的
uint64
),如果这可以扩展您的范围足够大的话


感谢Joachim提供了指向C++11枚举用法示例的链接:

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

#include <cstdint>

enum VStates : uint64_t {
    // Values
}
#包括
枚举VStates:uint64\t{
//价值观
}
另一方面,我建议不要计算出所有的二次幂。你在计算中犯了一个错误,写了一个十六进制常数,但给它一个以10为基数的数字。但是,与其重新计算所有这些,我建议如下:

#include <cstdint>

enum VStates : uint64_t {
    NEUTRAL = 0ULL,
    DRY = 1ULL << 0,
    WET = 1ULL << 1,
    HOT = 1ULL << 2,
    COLD = 1ULL << 3,
    // etc.
}
#包括
枚举VStates:uint64\t{
空档=0满,

DRY=1all枚举有31个非零值,因此它们都可以放入32位无符号值中。问题是这里的值不是位值。要么将它们作为十进制值写入(从前面删除
0x
),要么将它们作为十六进制值写入(0x01、0x02、0x04、0x08、0x10、0x20、0x40等)我个人不喜欢,但有些人用移位来写这种常数:1(注意:为了使我的答案完整,我将添加一些我没有花时间注意到但其他人已经指出的内容:您使用的是
0x
前缀,这意味着您的数字将被解释为十六进制。它们实际上不是二的幂,并且您的位标志测试也不会起作用!)

如果您的枚举像这样失控,请不要使用枚举类型。请使用类似于的类型。这样,您的枚举就可以是集合中位位置的简单编号名称列表…并且不会以指数方式耗尽枚举空间

例如:

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";
}
…如果您想将所有位设置为false,您可以选择:

state.reset();

不是答案,但如果这些值被写为十六进制常量,那么写和读就会简单得多。@PeteBecker:它们实际上被写为十六进制常量——但看起来他使用了十进制常量的数字(例如,他有0x00000512,实际上应该是512或0x200)。您知道
0x00000016
不是16吗?如果它们是用十进制常量而不是十六进制常量初始化的,那么它们可能适合您的枚举。请参阅例如关于强类型枚举以及如何定义它们。使用不同的整数类型。@JoachimPileborg谢谢,介意我使用该链接来改进答案吗?这是一个比我更好的答案,当您纠正真正的根本问题时。对标志集合而不是枚举使用
std::bitset
。比使用枚举进行索引更好的是将其包装在一个类中,该类将
std::bitset
作为具有命名成员访问函数的私有成员。
类VStates{public:bool is_dry()const{return bits[1];} ... }
@DavidStone谢谢。如果包装信息对这些观众感兴趣,那么我的可能会感兴趣……我可能最终会使用它。我目前正在开发一个应用程序,其中约2/3的时间用于复制数据。我的相关数据结构的大小减少了50%,相应的运行时间减少了不到30%e、 似乎我的应用程序至少有一部分可以接受该解决方案。@我考虑将其与DavidStone分开打包,因为它的构建依赖关系更简单,应用程序也更常见。很容易将NState.hpp和NState.cpp文件切掉以试用它,但如果有人认真使用它,请告诉我我会将其标准化。需要对C++11的内容(如move construction/等)进行重新访问。有趣的是,在这篇文章发表后的一两天,我就有机会使用它。我最终将我的评论和你的答案结合起来。我创建了一个类,其中包含一个
enum{value0,value1,value2,…,END}
。该类有一个
std::bitset
成员,我使用成员函数
is\u set(Enum e)访问这些值const
。这让我可以确定,无论我如何更改合法值的数量,我都会为正确的位置编制索引。这似乎是两个世界中最好的一个。我很好奇,对于移位,您不喜欢什么?它们不太容易出错,只需快速浏览一下枚举,您马上就会知道可以对其使用位操作它。@Joe-这纯粹是美学上的。它们不比十六进制值更容易出错,而且我认为它们很难看。
state.reset();