我正在寻找一种方便的习惯用法来检查两个有符号整数(
long
s或long long
s)的乘法是否会在C++版本中溢出,其中有符号算术溢出是未定义的行为(C或C++17和较早)。我可以使用 C++17 中可用的任何库函数,但在理想的情况下,我希望有比整数除法更便宜的东西(例如,根据论据)。在理想的情况下,解决方案将是编译器可以优化的东西(因此也不必一次手动执行一个字的乘法)。我想避免任何先执行乘法,然后对结果进行健全性检查的习惯用法,因为编译器可能会基于有符号算术不能溢出的假设删除健全性检查。 (毕竟,溢出是未定义的行为,因此编译器可以假设程序员永远不会让这种情况发生。)不幸的是,我见过的大多数建议的算法都是这种形式,所以看起来是不安全的。这无法优化,依赖于 C++20 和 HW 指令集支持。但应该比除法更快:
b <= std::numeric_limits<long long>::max() / a
b >= std::numeric_limits<long long>::lowest() / b
为 UB。这些情况需要特殊的计划和治疗。对操作数进行一些右移技巧取决于平台。
除了最小的无符号情况外,该解决方案涵盖了任何二进制(实际上是每个 std)平台上的所有其他位模式,但它最终绑定到二进制平台。