c++ - 哪些枚举值在 C++14 中是未定义的行为,为什么?

标签 c++ enums c++14 language-lawyer undefined-behavior

标准中的脚注暗示任何枚举表达式值都是已定义的行为;为什么 Clang 的未定义行为 sanitizer 程序会标记超出范围的值?

考虑以下程序:

enum A {B = 3, C = 7};

int main() {
  A d = static_cast<A>(8);
  return d + B;
}

the undefined behavior sanitizer下的输出是:

$ clang++-5.0 -fsanitize=undefined -ggdb3 enum.cc && ./a.out 
enum.cc:5:10: runtime error: load of value 8, which is not a valid value for type 'A'

请注意,错误不在static_cast 上,而是在添加上。当一个 A 被创建(但没有初始化)然后一个值为 8 的 intmemcpy 放入 时也是如此A - ubsan 错误发生在添加上,而不是初始加载上。

IIUC,较新的 clang 中的 ubsan 确实在 C++17 模式下标记了 static_cast 上的错误。我不知道那个模式是否也发现了 memcpy 中的错误。无论如何,这个问题都集中在 C++14 上。

报告的错误符合标准的以下部分:

dcl.enum :

For an enumeration whose underlying type is fixed, the values of the enumeration are the values of the underlying type. Otherwise, the values of the enumeration are the values representable by a hypothetical integer types with minimal range exponent M such that all enumerators can be represented. The width of the smallest bit-field large enough to hold all the values of the enumeration type is M. It is possible to define an enumeration that has values not defined by any of its enumerators. If the enumerator-list is empty, the values of the enumeration are as if the enumeration had a single enumerator with value 0.100

因此枚举 A 的值是 0 到 7(含),“范围指数”M 是 3。评估类型 A 的表达式 根据 expr.pre,值为 8 是未定义的行为:

If during the evaluation of an expression, the result is not mathematically defined or not in the range of representable values for its type, the behavior is undefined.

但有一个小问题:footnote from dcl.enum阅读:

This set of values is used to define promotion and conversion semantics for the enumeration type. It does not preclude an expression of enumeration type from having a value that falls outside this range. [emphasis mine]

问题:如果“[dcl.enum] 不排除枚举类型的表达式具有以下值,那么为什么值为 8 且类型为 A 的表达式未定义行为超出这个范围”?

最佳答案

Clang 会标记对超出范围的值使用 static_cast。如果整数值不在枚举范围内,则行为未定义。

C++ standard 5.2.9 Static cast [expr.static.cast] paragraph 7

A value of integral or enumeration type can be explicitly converted to an enumeration type. The value is unchanged if the original value is within the range of the enumeration values (7.2). Otherwise, the resulting enumeration value is unspecified / undefined (since C++17).

关于c++ - 哪些枚举值在 C++14 中是未定义的行为,为什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54379993/

相关文章:

c++ - 将无符号字符数组转换为整数

c++ - "a variable declared with an auto specifier cannot appear in its own initializer"

c++ - 在 C++ 中 : Is it possible to have a named enum be continued in a different file?

c# - 在 ASP.NET MVC 3 中使用枚举

java - Spring MVC @RequestBody 映射 Optional<Enum>

c++ - 如果基类受到保护,则无法访问派生类中的转换

c++ - 如何检查指针是否指向正确对齐的内存位置?

c++ - openMP过度同步

c++ - Qt : How to make a dynamically added item not comply to style sheet set at design time

c++ - 编译时 Visual Studio 2008 环境变量的使用