0

0

c++中如何判断整数溢出_c++检查加减法是否溢出的安全方法【详解】

冰火之心

冰火之心

发布时间:2026-01-22 16:10:42

|

472人浏览过

|

来源于php中文网

原创

C++23中推荐使用std::add_overflow和std::sub_overflow进行安全加减,语义清晰、无副作用、支持所有整型;若不支持C++23,可用GCC/Clang的__builtin_add_overflow等内置函数;手动检查易出错,需运算前判断且注意类型提升与符号边界。

c++中如何判断整数溢出_c++检查加减法是否溢出的安全方法【详解】

std::add_overflowstd::sub_overflow 做安全加减(C++23)

这是目前最直接、标准且无副作用的方案,但仅限 C++23 起可用。它不依赖编译器内置函数或手动位运算,语义清晰,返回 bool 表示是否溢出,并通过输出参数写入结果。

  • 必须包含
  • 函数签名是 std::add_overflow(a, b, &result),返回 true 表示溢出,此时 result 值未定义
  • 支持所有有符号/无符号整型,但两个操作数类型需相同,且 result 类型必须匹配
  • 不改变原值,不引发未定义行为,比手写条件判断更可靠
int a = INT_MAX;
int b = 1;
int result;
if (std::add_overflow(a, b, &result)) {
    // 溢出处理:例如抛异常、返回错误码、截断等
} else {
    // result == INT_MIN(补码下溢出结果),但这是由函数保证的合法值,非未定义行为
}

用编译器内置函数 __builtin_add_overflow(GCC/Clang)

在 C++23 不可用的项目中,这是最常用、高效且被广泛验证的方式。它本质是编译器生成的单条带进位指令检查,零运行时开销。

  • 仅 GCC 5+ / Clang 3.4+ 支持,MSVC 不支持(需换用 _addcarry_u32 等内联汇编或 SafeInt 库)
  • 三个参数:__builtin_add_overflow(a, b, &result),语义与 std::add_overflow 一致
  • 注意:abresult 类型必须完全一致(如全为 int),否则编译失败或行为未定义
  • 不能用于浮点数,也不能用于类类型;对 charshort 会先整型提升,需显式转成 int* 接收结果
long x = LONG_MAX;
long y = 1L;
long sum;
if (__builtin_add_overflow(x, y, &sum)) {
    // 处理溢出
}

手动检查加法溢出的边界条件(可移植但易错)

对有符号整数,不能只看结果值——因为溢出后行为是未定义的,任何基于 a + b 的比较都可能被编译器优化掉。正确做法是**在运算前判断**。

  • 对于 int 加法:a > 0 && b > 0 && a > INT_MAX - b 表示正溢出;a 表示负溢出
  • 无符号加法更简单:a + b (利用模运算特性),但前提是 ab 是无符号类型,否则隐式转换可能掩盖问题
  • 常见错误:写成 if (a + b > INT_MAX) —— 这段代码本身触发未定义行为,编译器可能直接删掉整个分支
  • 模板封装时要注意类型推导:用 std::numeric_limits::max() 替代硬编码常量,但需确保 T 是整型且非 bool

减法和乘法的溢出检查要点

减法可统一转为加法检查(a - ba + (-b)),但要注意 INT_MIN - (-1) 这类情况:对有符号数,-INT_MIN 本身溢出,所以不能直接算 -b 再传给加法检查函数。

笔尖Ai写作
笔尖Ai写作

AI智能写作,1000+写作模板,轻松原创,拒绝写作焦虑!一款在线Ai写作生成器

下载

立即学习C++免费学习笔记(深入)”;

  • 推荐仍用 std::sub_overflow__builtin_sub_overflow,它们内部已处理该 corner case
  • 乘法没有标准库函数(C++23 也未加入),__builtin_mul_overflow 是 GCC/Clang 提供的对应版本,用法一致
  • 若只能手写乘法检查,需分四象限讨论符号,并用除法反向验证(如 b != 0 && a > INT_MAX / b),但要小心除零和舍入误差
  • 所有检查都应在同一类型宽度下进行,避免中间计算因类型提升引入新溢出(例如 int8_t * int8_t 结果应存入 int16_t 再判断)

实际工程中,最容易被忽略的是:溢出检查本身不能成为性能瓶颈,也不应掩盖真正的逻辑错误。比如在循环计数器中频繁调用检查函数,不如改用更大类型(int64_t)或静态断言约束输入范围。而一旦选择检查,就必须覆盖所有路径——尤其是混合类型运算、模板实例化、以及从用户输入直接参与算术的边界点。

相关专题

更多
java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1489

2023.10.24

if什么意思
if什么意思

if的意思是“如果”的条件。它是一个用于引导条件语句的关键词,用于根据特定条件的真假情况来执行不同的代码块。本专题提供if什么意思的相关文章,供大家免费阅读。

757

2023.08.22

string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

338

2023.08.02

int占多少字节
int占多少字节

int占4个字节,意味着一个int变量可以存储范围在-2,147,483,648到2,147,483,647之间的整数值,在某些情况下也可能是2个字节或8个字节,int是一种常用的数据类型,用于表示整数,需要根据具体情况选择合适的数据类型,以确保程序的正确性和性能。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

542

2024.08.29

c++怎么把double转成int
c++怎么把double转成int

本专题整合了 c++ double相关教程,阅读专题下面的文章了解更多详细内容。

53

2025.08.29

C++中int的含义
C++中int的含义

本专题整合了C++中int相关内容,阅读专题下面的文章了解更多详细内容。

197

2025.08.29

Golang 性能分析与pprof调优实战
Golang 性能分析与pprof调优实战

本专题系统讲解 Golang 应用的性能分析与调优方法,重点覆盖 pprof 的使用方式,包括 CPU、内存、阻塞与 goroutine 分析,火焰图解读,常见性能瓶颈定位思路,以及在真实项目中进行针对性优化的实践技巧。通过案例讲解,帮助开发者掌握 用数据驱动的方式持续提升 Go 程序性能与稳定性。

6

2026.01.22

html编辑相关教程合集
html编辑相关教程合集

本专题整合了html编辑相关教程合集,阅读专题下面的文章了解更多详细内容。

47

2026.01.21

三角洲入口地址合集
三角洲入口地址合集

本专题整合了三角洲入口地址合集,阅读专题下面的文章了解更多详细内容。

24

2026.01.21

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
最新Python教程 从入门到精通
最新Python教程 从入门到精通

共4课时 | 12.4万人学习

Rust 教程
Rust 教程

共28课时 | 4.7万人学习

Git 教程
Git 教程

共21课时 | 2.9万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号