2013-05-14 70 views
2

我正在编译为GCC编写的代码,在Visual C++ 2012中。我收到以下枚举引发的有关enum值截断的警告(由于值超出了int范围) :任意大小的枚举值

enum tile_flags { 
    TILE_FLAG_INNER_FLAME= 0x10000000ULL, 
    TILE_FLAG_CONSTRICTED= 0x20000000ULL, 

    TILE_FLAG_MIMIC_INEPT 0x2000000000ULL 
    TILE_FLAG_MIMIC 0x4000000000ULL 
    TILE_FLAG_MIMIC_RAVEN 0x6000000000ULL 
    TILE_FLAG_MIMIC_MASK 0x6000000000ULL 
} 

当编译为x86时,它会出现MSVC只是截断枚举值,以适应32位。但是,在GCC中不会发生截断。 GCC上发生了什么?我该如何为MSVC做这项工作?

回答

10

从N3485,§7.2/6:

对于枚举其基础类型不固定成本,基础类型是可以 代表所有在枚举定义枚举值德音响整型。如果没有整数类型可以表示所有的枚举数值,则枚举是不合格的。它是实现定义的,除了基本类型不应该大于int,除非 枚举器的值不能在int或unsigned int中填充,否则使用整数类型 作为基础类型。如果枚举列表是空的,基本型是 仿佛枚举具有值为一个枚举0

因此,如果MSVC有必要long long支持,应该使底层的类型无论如何。看到它没有,你可以尝试一件事来哄它。

指定的基本类型:如果你需要更多的条目比unsigned long long可以帮你,请尝试使用结构

enum tile_flags : unsigned long long { 
    ... 
}; 
+1

哇,不知道你能做到这一点!类型'tile_flags'是否还有类型安全性,还是编译器在这种情况下将它视为'unsigned long long'? – RandyGaul 2013-05-14 17:46:16

+4

@RandyGaul,是的,它仍然是一个独特的类型。它只是使用无符号的long long来存储值。这是一个C++ 11功能。你也可以有范围的枚举,它强制你使用'EnumName :: Value'并且不会隐式地转换为整数。 – chris 2013-05-14 17:48:56

+0

太好了,谢谢分享。 – RandyGaul 2013-05-14 17:49:17

0

struct tile_flags { 
    bool innerFlame : 1; 
    bool constricted : 1; 
    bool mimicInept : 1; 
    bool mimic : 1; 
    // etc 
}; 

这将使用位域,这通常意味着值将尽可能紧密地包装,并且虽然它可以使构建比传统的旗号更难一点,但是它是最容易的选项,其超过sizeof unsigned long long比特。