Enum警告:超出范围
Enum warning : outside the range
我有以下代码。有两个枚举。一个有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
的底层类型表示的。
相关文章:
- 为什么 gcc 会给我可能未初始化的警告 deque::insert 带有过滤范围
- 为什么 gcc 警告只针对统一初始化缩小转换范围?
- gcc8.2如何启用警告:数组下标在数组范围之上[-warray-bounds]
- 使用范围用于向量的循环时,CppCorechecker C风格警告
- 为什么我在C++中收到有关此基于范围的 for 循环的警告
- 如何处理警告 C4177:#pragma 'float_control' 只能在全局范围或命名空间范围内使用
- 正在缩小MSVC中到布尔警告的转换范围
- 误报警告 PVS 工作室:V821 性能降低。'rhs'变量可以在较低级别的范围内构造
- #pragma警告(disable:XXXX)的行为与预期不符(范围问题)
- 警告缩小转换范围(uint32 到 uint8)
- 警告:缩小转换范围 C++11
- 使用范围防护时如何避免警告
- 在Qt Creator中禁用编译器警告项目范围(当使用MSVC时)
- 在Visual Studio 2015社区C ++中,如何修复警告C4838:从'unsigned int'到'int'的转换需要缩小转换范围
- 定义要在全局范围内运行而不发出警告的宏
- Visual C++中的 C4510-C4513 和 C4623-C4626 警告范围有什么区别?
- 编译器警告使用范围外变量的内存
- 从文字缩小范围不会引起警告
- Enum警告:超出范围
- Visual Studio 2005 - 处理C++ "initialized but not referenced"范围帮助程序破坏警告?