最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
C++如何检查一个整数在加法时是否溢出
时间:2026-07-10 10:27:52 编辑:袖梨 来源:一聚教程网
C++23起应优先使用std::add_overflow判断整数加法溢出,它返回bool表示是否溢出,并通过输出参数写入结果;此前可用GCC/Clang的__builtin_add_overflow;纯标准C++需按符号分情况预判,避免中间运算溢出。
用 std::add_overflow 判断加法溢出(C++23 起)
如果你用的是支持 C++23 的编译器(如 GCC 13+、Clang 16+、MSVC 19.35+),最直接的方式就是调用标准库提供的 std::add_overflow。它专为整数溢出检测设计,语义清晰、无需手写逻辑,且能跨平台保证行为一致。
常见错误是误以为 std::add_overflow 返回 bool 表示“是否成功”,其实它返回 bool 表示“是否溢出”,同时通过输出参数写入结果值(若未溢出):
-
std::add_overflow(a, b, &result):若未溢出,result被设为a + b;若溢出,result值未定义,函数返回true - 只对有符号/无符号整型有效,不支持浮点或自定义类型
- 注意传入的第三个参数必须是左值引用(
&result),不能是临时变量或字面量
GCC/Clang 内置函数 __builtin_add_overflow
在 C++23 不可用时(比如项目还卡在 C++17),GCC 和 Clang 提供了等效的内置函数,行为与 std::add_overflow 几乎一致,兼容性更好。
典型误用是忽略返回值或搞错参数顺序——它始终是三参数:两个操作数 + 一个输出地址:
立即学习“C++免费学习笔记(深入)”;
-
__builtin_add_overflow(a, b, &result)返回true表示溢出,false表示成功 - 所有参数类型需严格匹配(例如
int加int,不能混用long long和int,否则可能触发未定义行为) - MSVC 不支持该内置函数,若需跨编译器,得加宏判断:
#ifdef __GNUC__ || defined(__clang__)
手动检查:先判断符号再比较边界
纯标准 C++(任意版本)下,可以靠数学逻辑判断溢出,但容易写错。关键不是“算完再检查”,而是“加之前就预判”。
以有符号 int 为例,溢出只发生在同号相加时:
- 正 + 正 → 溢出当且仅当
a > INT_MAX - b(避免先加再比,防止 UB) - 负 + 负 → 溢出当且仅当
a - 异号相加不会溢出(和一定在范围内)
- 无符号整数更简单:只要
a + b 就溢出(利用模运算回绕特性)
注意:直接写 a + b > INT_MAX 是错的——这行代码本身就会触发未定义行为,编译器可能优化掉整个分支。
为什么不能依赖 std::numeric_limits<T>::max() 直接加?
很多人试图这样写:if (a > std::numeric_limits<int>::max() - b)</int>,看似合理,但实际有隐藏陷阱:
- 减法本身可能溢出:比如
b是负数,INT_MAX - (-1)就越界了 - 类型提升问题:
std::numeric_limits<int>::max()返回int,但参与运算时可能被提升为long或unsigned,导致比较失效 - 无符号类型没有“负数”概念,
max() - b在b > max()时会回绕,结果不可靠
所以预判逻辑必须按符号分情况,且所有中间运算都得落在安全范围内。