使用size_t进行反向循环时,for(size_t i = n; i >= 0; i--)会因无符号回绕导致无限循环,i减至0后变为size_max(如18446744073709551615),使条件恒真,最终读到极大数值而非真正变大。

循环结束后变量值比预期大,通常不是“变大了”,而是你没意识到循环根本没停——最常见原因是用 size_t 做反向循环时写错了终止条件。
用 size_t 写 for (size_t i = n; i >= 0; i--) 会无限循环
因为 size_t 是无符号类型,它不能表示负数。当 i 减到 0 后再执行 i--,结果不是 -1,而是回绕成 SIZE_MAX(比如 18446744073709551615)。于是 i >= 0 永远为真,循环卡死,i 在后续迭代中不断递减、回绕、再递减……最终你看到的“比预期大”的值,其实是某次回绕后读到的极大数值(比如 126、4294967295),而不是变量真的被加多了。
- 典型错误代码:
for (size_t i = 10; i >= 0; i--) { /* ... */ } - 真实行为:i 从 10 → 0 → 18446744073709551615 → 18446744073709551614 → ……
- 后果不只是“值变大”,还常伴随越界访问、崩溃或静默数据损坏
++i 和 i++ 在循环中不会导致终值异常,但可能掩盖逻辑问题
有人误以为 i++ 比 ++i “慢”或“多算一次”,从而怀疑终值偏差。其实对内置整型(如 int)来说,两者在循环末尾的终值完全一致——都是循环结束时的最终值。区别只在循环体内表达式求值的时机:
for (int i = 0; i 和 <code>for (int i = 0; i 生成的汇编几乎一样,终值都是 <code>n- 真正影响终值的是循环条件和步进逻辑,不是前/后置自增
- 但在自定义类型(如迭代器)中,
i++会构造临时对象,若迭代器实现有副作用或调试输出,可能干扰观察
多线程下 ++counter 看似执行了 N 次,实际终值却偏小——但不是“变大”
如果你观察到终值“比预期小”,那很可能是竞态:多个线程同时执行 ++counter,而该操作不是原子的(load-modify-store 三步分离)。但注意,这种情况不会让值“变大”,只会丢失更新、导致终值偏低。如果终值反而异常偏大,要检查是否:
- 循环体被意外重复执行(比如条件判断写错、goto 跳转失控)
- 变量被多个作用域无意修改(全局变量 + 多个函数写入)
- 内存越界踩坏了相邻变量,导致计数器被其他逻辑意外改写
最值得反复确认的,是循环变量类型与终止条件的匹配性。哪怕只漏看一个 >= 0,就足以让程序进入不可预测的数值荒原。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











