Enum警告:超出范围

Enum warning : outside the range

本文关键字:范围 警告 Enum      更新时间:2023-10-16

我有以下代码。有两个枚举。一个有16个值(A_)和另一个有15个值(A1_)。

#include <iostream>
typedef enum
{   
    A_0 = 0,
    A_1,
    A_2,
    A_3,
    A_4,
    A_5,
    A_6,
    A_7,
    A_8,
    A_9,
    A_10,
    A_11,
    A_12,
    A_13,
    A_14,
    A_15,
    A_FIRST = A_0,
    A_LAST = A_15
} a_t;
typedef enum
{   
    A1_0 = 0,
    A1_1,
    A1_2,
    A1_3,
    A1_4,
    A1_5,
    A1_6,
    A1_7,
    A1_8,
    A1_9,
    A1_10,
    A1_11,
    A1_12,
    A1_13,
    A1_14,
    A1_FIRST = A1_0,
    A1_LAST = A1_14
} a1_t;
int 
main()
{   
    a_t m = static_cast<a_t> (static_cast<int> (A_LAST) + 1); // WARNING
    std::cout << m;
    a1_t m1 = static_cast<a1_t> (static_cast<int> (A1_LAST) + 1); // NO WARNING
    std::cout << m1;
    return 0;
}

g++编译:

g++ -Wconversion enum_testing.cpp

我得到一个警告消息:

enum_testing.cpp: In function ‘int main()’:
enum_testing.cpp:49:64: warning: the result of the conversion is     unspecified because ‘16’ is outside the range of type ‘a_t’ [-Wconversion]
     a_t m = static_cast<a_t> (static_cast<int> (A_LAST) + 1);

问题:为什么我得到一个警告消息,第一次声明与enum A_,而不是与enum A1_的消息。

枚举的取值范围为:

[…如果底层类型不固定,则范围为所有值最小的位域可能大到足以容纳所有目标枚举的枚举数[…]

所以15符合这个范围,而16不符合。这在c++ 17之前是未定义的行为,在c++ 17之后将是未定义的行为。更改是由于DR 1766:值超出了枚举值的范围,该枚举值表示:

尽管第1094号问题澄清了在转换为枚举类型后,枚举类型表达式的值可能不在枚举值的范围内(参见5.2.9 [exp .static])。(强制转换]第10段),结果只是一个未指定的值。考虑到未定义行为会使表达式变成非常量,这可能需要加强以产生未定义行为。参见9.6[类]。第4段

,解决方案是使其为未定义行为

问题是编译器可以自由选择任何底层类型,只要它足够大,就可以让enum声明保存所有数据。

在你的例子中,它显然选择了一个整数类型来表示a_t,它的位长(可能是虚构的)为4。

该类型只能保存0到15之间的值。您尝试static_cast<a_t> (16),它在可表示的值之外,因此是未定义的行为。这对于a1_t来说是不正确的-你很幸运-因为这里它将是static_cast<a1_t> (15),而15是由a1_t的底层类型表示的。