问题描述
#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
和 a
的类型为 b
且 int
为 a
和 INT_MIN
时,b
显然是 UB是 INT_MAX
,因为有符号溢出是未定义的行为。
当有符号整数算术运算溢出(结果不适合结果类型)时,行为未定义
在计算完成之前,您不会转换为 int64_t
。