一聚教程网:一个值得你收藏的教程网站

最新下载

热门教程

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 表示成功
  • 所有参数类型需严格匹配(例如 intint,不能混用 long longint,否则可能触发未定义行为)
  • 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,但参与运算时可能被提升为 longunsigned,导致比较失效
  • 无符号类型没有“负数”概念,max() - bb > max() 时会回绕,结果不可靠

所以预判逻辑必须按符号分情况,且所有中间运算都得落在安全范围内。

热门栏目