商城首页欢迎来到中国正版软件门户

您的位置: 首页 > 文章列表 > 编程开发 > C++ long long类型范围 _ 大整数存储与溢出处理【实战】

C++ long long类型范围 _ 大整数存储与溢出处理【实战】

  发布于2026-07-19 阅读(0)

扫一扫,手机访问

long long 的精确范围:不是“大约 9e18”,而是精确到个位

先说结论:long long 能存的最大值是 9223372036854775807,最小值是 -9223372036854775808。想象一下,这是一个 19 位数,从 -9.2e18 到 9.2e18。但它的危险之处在于,超出这个范围后,编译器不会报错,只会给你一个不可预测的结果——这可能是整型溢出里最容易被忽视的坑。

C++ long long类型范围 _ 大整数存储与溢出处理【实战】

取值边界与字面量写法

这两个边界值必须带后缀,否则编译器可能按 intlong 解析,导致截断或警告。写常量时,务必加 LL(有符号)或 ULL(无符号),例如:9223372036854775807LL18446744073709551615ULL

更稳妥的做法是用 std::numeric_limits::max()min() 获取边界值,比硬编码更安全、可移植。sizeof(long long) 在所有主流平台(GCC/Clang/MSVC,x86_64 或 aarch64)下恒为 8 字节,这是个可以放心依赖的特性。

为什么 long long + 1 不一定等于 -9223372036854775808?

这是一个经典误区。很多人以为 LLONG_MAX + 1 会绕回到 LLONG_MIN,但 C++ 标准明确说:有符号整数溢出是未定义行为(UB)。编译器可以生成任何结果——绕回、崩溃、优化掉整个分支,甚至静默返回错误值。你看到的“绕回”只是常见表现,不是保证。实操中,开启 UBSan 检测(编译加 -fsanitize=undefined)会在运行时直接报错并指出溢出位置;-ftrapv(GCC 特有)则会让溢出触发 SIGABRT,但仅对有符号类型有效,且影响性能。

还有一个坑:别用 double 中转判断是否溢出。double 只能精确表示 ≤ 2⁵³ 的整数,而 long long 能到 2⁶³,中间存在大量无法准确表达的值,容易误判。

安全做加减乘运算的实操方式

手动检查溢出比依赖运行时检测更可控,尤其在性能敏感或嵌入式场景中。这里给几个干货:

  • 加法检查:如果 a > 0 && b > std::numeric_limits::max() - a,说明会溢出;如果 a < 0 && b < std::numeric_limits::min() - a,说明会下溢。
  • 乘法更复杂,推荐用编译器内置函数:__builtin_mul_overflow(a, b, &result),返回 true 即溢出,且不触发 UB。
  • 若逻辑允许,优先改用模运算提前降维,比如把 (a * b) % MOD 拆成 ((a % MOD) * (b % MOD)) % MOD
  • 对计数类变量,考虑用 int64_t 替代 long long——语义更明确,且 是标准头文件,跨平台兼容性更好。

什么时候该放弃 long long,换真正的大整数?

当你的计算涉及阶乘、组合数、高精度中间结果(比如 10^18 × 10^18),或者需要精确到百位以上时,long long 就不够用了。这时有几种选择:

  • __int128(GCC/Clang 扩展)支持 128 位有符号整数,但 MSVC 不支持,跨平台项目慎用。
  • boost::multiprecision::int128 提供类似接口,封装了底层差异,适合需要 128 位但不想手写进位逻辑的场景。
  • 生产级高精度需求(如密码学、金融计算)请用 OpenSSL BN_*libgmp,它们经过充分测试,支持任意长度。

真正容易被忽略的不是“它能存多大”,而是“它溢出时不说话”——所有防御手段都得在溢出发生前就部署到位,而不是等它翻车后再补救。

本文转载于:https://www.php.cn/faq/2317956.html 如有侵犯,请联系zhengruancom@outlook.com删除。
免责声明:正软商城发布此文仅为传递信息,不代表正软商城认同其观点或证实其描述。

热门关注