
一起动脑筋 · 先看一个小故事
一个玩具计数器只有两位,99 再加 1 就装不下了。计算机的整数类型也有范围。
把过程摊开来看
- 先查范围类型最多能表示多少
- 估计结果乘法可能比输入大很多
- 选好类型计算前就用足够范围
- 再做检查确认输入也合法
整数类型只能表示有限的数。输入都放得下,不代表相加或相乘也放得下。
例如两个接近十万的数相乘,结果接近一百亿,常见的 32 位 int 放不下。
01为什么数字会“装不下”?
计算机用有限数量的 Bit 保存整数,所以每种整数类型能表示的范围也是有限的。
就像只有 3 位十进制数字的计数器最多只能直接显示 999,固定宽度整数也有自己的最大值和最小值。
0232 位 int 大概能有多大?
在最常见的 32 位 int 实现中,范围通常是:
但再次强调:C++ 标准不保证 int 一定是 32 位。
03有符号整数溢出会怎样?
int x = 2147483647;
x = x + 1;
如果这里的 int 最大值确实是 2147483647,那么这次加法结果超出可表示范围。
04无符号整数为什么不一样?
无符号整数有明确的模运算规则。
对于 N 位无符号整数,结果按模 2^N 计算。
unsigned int x = UINT_MAX;
x = x + 1; // 结果回到 0
这叫回绕(wraparound),是语言定义好的行为。
05怎样减少溢出风险?
选更合适的类型
需要更大范围时使用更宽整数类型。
先估算范围
理解输入和中间结果最大可能多大。
运算前检查
必要时先判断是否会越界。
注意中间结果
最终结果能装下,中间计算也可能先溢出。
06为什么 long long 常常有用?
在信奥题中,long long 常用于需要更大整数范围的场景。
C++ 标准保证 long long 至少有 64 位的数值宽度要求,现代常见实现通常是 64 位。
long long total = 1000000000LL * 1000000000LL;
这里的 LL 让字面量参与更宽的整数运算,避免先用较小类型计算。
07中间结果为什么最容易被忽略?
int a = 100000;
int b = 100000;
long long c = a * b;
即使 c 是 long long,右边的 a * b 仍可能先按 int 计算并溢出。
更安全的写法之一:
long long c = 1LL * a * b;
你已经知道了什么
- 整数类型只能表示有限范围。
- 有符号整数溢出在 C++ 中属于未定义行为。
- 无符号整数按模
2^N回绕。 - 更宽类型可以扩大范围,但也要注意中间表达式的类型。
- 信奥中
long long很常用,但仍要学会估算范围。
本专题完成:下一专题可以继续进入“程序流程”。
轮到你来试一试
先用 int 做乘法,最后存进 long long,就一定安全吗?
想好了吗?点开看解释
不一定。乘法可能已在 int 中溢出。要让运算在足够大的类型中进行,而不只是把最终容器换大。