我有以下代码。有两个枚举。一个有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);
问题:为什么我收到包含枚举A_的第一次声明的警告消息,而不是包含枚举A1 _的消息。
答案 0 :(得分:1)
enum的范围是:
[...]如果基础类型未修复,则范围是所有值 可能的最小位域足够容纳所有 目标枚举的枚举器[...]
因此15
符合此范围,而16
则不符合此范围。这是C ++ 17之前的未指定行为,之后将是未定义的行为。这一变化归因于DR 1766: Values outside the range of the values of an enumeration ,其中说:
虽然问题1094澄清了枚举类型的表达式的值可能不在转换为枚举类型后的枚举值的范围内(参见5.2.9 [expr.static.cast]第10段) ,结果只是一个未指定的值。鉴于未定义的行为使表达式非常量,这应该可以加强以产生未定义的行为。另见9.6 [class.bit]第4段。
并且解决方案是使其成为未定义的行为。
答案 1 :(得分:0)
问题在于编译器可以自由选择任何基础类型足以使枚举声明保存其所有数据。
在你的情况下,它显然选择了一个整数类型来表示a_t
,其中(可能是虚构的)位数为4。
此类型只能保存0到15之间的值。您可以尝试static_cast<a_t> (16)
,它在可表示的值之外,因此是未定义的行为。 a1_t
不是这样的 - 你得到了幸运&#34; - 因为这里static_cast<a1_t> (15)
和15可由a1_t
的基础类型表示。