5

当我运行以下代码时 - 我收到警告“从 int 到 {} 内的 long unsigned int 的缩小转换在 C++11 [-Wnarrowing] 中格式错误。我使用的是 GNU 4.8 编译器。

typedef struct TableEntry
{
    unsigned long value;
    const char *label;
} TableEntry;

enum FunctionType
{
    NORMAL   = 0, 
    RANGE    = 1
};


TableEntry functionTypes[] = 
{
    {NORMAL,   "NORMAL"},
    {RANGE, "RANGE"}
};

我不明白为什么编译器将枚举视为 int?
这是 GCC 4.8 中的错误吗?有什么解决方法吗?任何帮助表示赞赏。

4

4 回答 4

7

如果可行的话:

enum FunctionType
{
    NORMAL   = 0, 
    RANGE    = 1
};

typedef struct TableEntry
{
    FunctionType value;
    const char *label;
} TableEntry;


TableEntry functionTypes[] = 
{
    {NORMAL,   "NORMAL"},
    {RANGE, "RANGE"}
};

否则,将结构中的类型更改为int,或显式地将枚举基于与结构中相同的类型。

顺便说一句,我认为 g++ 警告是没有根据和错误的,因为原始代码是有效的 C++03。 更正:据我所知,诊断是正确的,这是 C++11 中的一个重大变化。我简直不敢相信。


关于命名约定:那些全大写的标识符对 Java 程序员(他们习惯于该约定)来说是好的,但在 C++ 中,它们增加了无意中文本替换的机会。还有审美方面的考虑。在为宏保留所有大写字母方面取得了很大的胜利。

于 2014-02-12T00:03:43.523 回答
4

通常,无范围枚举的底层类型是 int (它可以是任何可以表示枚举数的所有值的整数类型)。

但是我没有看到任何缩小转换,因为 unsigned long 类型可以表示 int 类型的所有值。

编辑:似乎我错了,因为我在标准中发现了一个与我的假设相矛盾的例子

unsigned int ui1 = {-1}; // error: narrows

所以 unsigned int 不能通过使用包含负数的初始化列表来初始化。

所以为了避免警告,枚举可以写成

enum FunctionType : unsigned int // or unsigned long
{
    NORMAL   = 0, 
    RANGE    = 1
};
于 2014-02-12T00:07:30.353 回答
2
  • 您可以将“值”更改为 int
  • 或者您可以使用强类型的新“枚举类”(c++11),并将您的“值”声明为这种类型。
于 2014-02-11T23:52:15.347 回答
0

由于您使用的是 c++11,因此您可以像这样声明您的枚举:
enum Enum2 : unsigned char;
这应该强制枚举工作。也就是说,IDEONE 对您发布的代码没有警告/错误。可能只是 GCC 过于迂腐。

于 2014-02-12T03:41:56.180 回答