C 和 C++ 中,无符号整数(如 unsigned int)的溢出是定义良好的行为,即发生溢出时,值会回绕(wrap around)到 0。这种行为基于模运算。实际编程中,如果对溢出有严格要求(例如,防止数组越界、缓冲区溢出等),务必进行溢出检测。

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;
}

推荐文档