我有一个遗留代码库,我们正在尝试将其迁移devtoolset-4
到devtoolset-7
. 我注意到一个关于有符号整数溢出的有趣行为(int64_t
具体来说是 )。
有一个代码片段用于在乘以一大组整数时检测整数溢出:
// a and b are int64_t
int64_t product = a * b;
if (b != 0 && product / b != a) {
// Overflow
}
这段代码在 devtoolset-4 上运行良好。但是,使用 devtoolset-7,永远不会检测到溢出。
例如:当a = 83802282034166
和b = 98765432
时,
product
变为-5819501405344925872
(显然值已溢出)。
但product / b
结果等于a (83802282034166)
。因此,if
条件永远不会变为真。它的值应该是根据溢出(负)product
值计算出来的:-5819501405344925872 / 98765432 = -58922451788
具有讽刺意味的是,数学是正确的,但它导致了 devtoolset-4 的异常行为。
- 编译器是否可以缓存导致这种行为的值(而不是重新评估它)?
- 或者编译器优化是否将语句转换
product / b != a
为product != a * b
并达到相同的溢出值(或者可能只是跳过基于上述语句 where 的计算product = a * b
)?
我知道有符号整数溢出是 C++ 中的“未定义行为”,因此编译器行为可能会因实现而改变。但是有人可以帮我理解上述行为吗?
注意:devtoolset-4 和 devtoolset-7 中的 g++ 版本分别为g++ (GCC) 5.2
和g++ (GCC) 7.2.1
。