long long有符号最大值为9223372036854775807,最小值为-9223372036854775808,是C++11强制规定的64位整数范围,跨平台一致。

long long 能存多大?不是“大约 9e18”,而是精确到个位:−9223372036854775808 到 9223372036854775807。超出这个范围不报错,但结果不可预测——这是它最危险的特性。
long long 的取值边界和字面量写法
它的最大值是 9223372036854775807,最小值是 -9223372036854775808。这两个数必须带后缀,否则编译器可能按 int 或 long 解析,导致截断或警告。
- 写常量时务必加
LL(有符号)或ULL(无符号),例如:9223372036854775807LL、18446744073709551615ULL - 用
std::numeric_limits<long long>::max()</long>和min()获取边界值,比硬编码更安全、可移植 -
sizeof(long long)在所有主流平台(GCC/Clang/MSVC,x86_64 或 aarch64)下恒为8,可放心依赖
为什么 long long + 1 不一定等于 -9223372036854775808?
C++ 标准规定:有符号整数溢出是「未定义行为(UB)」。编译器可以生成任何结果——绕回、崩溃、优化掉整个分支,甚至静默返回错误值。你看到的 LLONG_MAX + 1 → LLONG_MIN 只是常见表现,不是保证。
- 开启 UBSan 检测:编译加
-fsanitize=undefined,运行时会直接报错并指出溢出位置 -
-ftrapv(GCC)会让溢出触发SIGABRT,但仅对有符号类型有效,且影响性能 - 别用
double中转判断是否溢出:double只能精确表示 ≤ 2⁵³ 的整数,而long long能到 2⁶³,中间存在大量无法准确表达的值
安全做加减乘运算的实操方式
手动检查溢出比依赖运行时检测更可控,尤其在性能敏感或嵌入式场景中。
立即学习“C++免费学习笔记(深入)”;
- 加法检查:
a > 0 && b > std::numeric_limits<long long>::max() - a</long>表示会溢出;a ::min() - a表示会下溢 - 乘法更复杂,推荐用编译器内置函数:
__builtin_mul_overflow(a, b, &result),返回true即溢出,且不触发 UB - 若逻辑允许,优先改用模运算提前降维,例如把
(a * b) % MOD拆成((a % MOD) * (b % MOD)) % MOD - 对计数类变量,考虑用
int64_t替代long long:语义更明确,且<cstdint></cstdint>是标准头文件,跨平台兼容性更好
什么时候该放弃 long long,换真正的大整数?
当你的计算涉及阶乘、组合数、高精度中间结果(比如 10^18 × 10^18),或者需要精确到百位以上时,long long 就不够用了。
-
__int128(GCC/Clang 扩展)支持 128 位有符号整数,但 MSVC 不支持,跨平台项目慎用 -
boost::multiprecision::int128提供类似接口,封装了底层差异,适合需要 128 位但不想手写进位逻辑的场景 - 生产级高精度需求(如密码学、金融计算)请用
OpenSSL BN_*或libgmp,它们经过充分测试,支持任意长度
真正容易被忽略的不是“它能存多大”,而是“它溢出时不说话”——所有防御手段都得在溢出发生前就部署到位,而不是等它翻车后再补救。


















