为什么g++-11'-O2'包含错误而'-O0'没问题?
#include <limits>
#include <cstdint>
#include <iostream>
template<typename T>
T f(T const a = std::numeric_limits<T>::min(),
T const b = std::numeric_limits<T>::max())
{
if (a >= b)
{
throw 1;
}
auto n = static_cast<std::uint64_t>(b - a + 1);
if (0 == n)
{
n = 1;
}
return n;
}
int main()
{
std::cout << f<int>() << std::endl;
}
g++-11 -std=c++20 -O2应该输出0比其他1!
clang++ 没问题。如果我-O2改为-O0,g++-11 也可以。
参见:在线演示
为什么 g++ -O2 包含一个错误而 -O0 可以?
回答
b - a + 1当aand bareint和aisINT_MIN和bis的类型为有INT_MAX符号溢出时,显然是 UB是未定义的行为。
来自cppreference:
当有符号整数算术运算溢出(结果不适合结果类型)时,行为未定义
int64_t直到计算完成后,您才转换为。
- Even though c++20 enforces 2's complement signed integers, it does not state anything new about overflows in this context
- @NathanOliver That rule is about integer conversions. It doesn't apply to arithmetic overflow.