1、 加法溢出检测
C++ 中,对于 无符号整数加法,溢出是定义良好的行为,即发生溢出时结果会回绕到 0
(模 2^n
)。尽管不会导致程序崩溃,但在某些应用(如加密、安全、金融等)中,我们希望能显式检测溢出。
1)比较结果是否小于任一操作数
#include <iostream> using namespace std; // 检测无符号整数加法是否溢出 bool addWillOverflow(unsigned int a, unsigned int b) { unsigned int result = a + b; return result < a || result < b; } int main() { unsigned int x = 4000000000; unsigned int y = 500000000; if (addWillOverflow(x, y)) { std::cout << "加法发生了溢出!" << std::endl; } else { unsigned int sum = x + y; std::cout << "加法没有溢出,结果是:" << sum << std::endl; } return 0; }
2)使用标准库函数(C++20)
#include <limits> #include <stdexcept> #include <iostream> #include <numeric> // for std::plus using namespace std; // 安全加法函数:检测无符号整数溢出 bool safeAdd(unsigned int a, unsigned int b, unsigned int& result) { if (b > std::numeric_limits<unsigned int>::max() - a) { return false; // overflow } result = a + b; return true; } int main() { unsigned int x = 4000000000; unsigned int y = 500000000; unsigned int sum = 0; if (safeAdd(x, y, sum)) { std::cout << "加法成功,结果为: " << sum << std::endl; } else { std::cout << "加法溢出,未能计算结果!" << std::endl; } return 0; }
2、乘法溢出检测
C++ 中,无符号整数(如 unsigned int
, uint32_t
, uint64_t
等)的 乘法溢出 是 定义良好行为,即它会回绕(wrap around)到 0 开始。但如希望检测是否发生了溢出,可以使用以下几种方法。
1)通过除法反推判断是否溢出
#include <iostream> #include <limits> using namespace std; bool mulWillOverflow(unsigned int a, unsigned int b) { // 乘零不会溢出 if (a == 0 || b == 0) return false; return a > std::numeric_limits <unsigned int>::max() / b; } int main() { unsigned int a = 100000; unsigned int b = 50000; if (mulWillOverflow(a, b)) { std::cout << "溢出检测:乘法将发生溢出\n"; } else { unsigned int result = a * b; std::cout << "结果:" << result << std::endl; } return 0; }
2)使用 GCC / Clang 内建函数
#include <iostream> using namespace std; bool safeMul(unsigned int a, unsigned int b, unsigned int& result) { return __builtin_umul_overflow(a, b, &result); } int main() { unsigned int a = 100000; unsigned int b = 50000; unsigned int result; if (safeMul(a, b, result)) { std::cout << "乘法发生了溢出\n"; } else { std::cout << "乘积是:" << result << std::endl; } return 0; }