C for 循环
更新时间:2026-08-26。本文是
languages/c/主题入门层第 15 篇。循环是程序里的"复读机",for 是其中最常用的一种。对本站来说循环还有特殊意义:性能剖析里 90% 的热点都长在循环里,perf火焰图找的就是循环。
本文要回答的问题
- for 的三个部分分别做什么?哪个可以省?
- 循环里声明变量和外面声明有什么区别?
- 为什么说"循环是性能分析的第一现场"?
一、for 的三要素
c
for (初始化; 条件; 更新) {
// 循环体
}c
for (int i = 0; i < 10; i++) {
printf("%d\n", i); // 打印 0~9
}三个部分的作用:
| 部分 | 作用 | 执行时机 |
|---|---|---|
int i = 0 | 初始化(只执行一次) | 进入循环前 |
i < 10 | 条件(为真继续) | 每次迭代前判断 |
i++ | 更新 | 每次迭代结束后 |
执行顺序:初始化 → 判断 → 循环体 → 更新 → 判断 → 循环体 → … 直到条件为假。
三个部分都可以省略(分号不能省):
c
int i = 0;
for (; i < 10; ) { // 相当于 while
if (某些条件) i++; // 更新挪到循环体里
}但省略太多就失去 for 的意义了——写 for (;;) 是无限循环(等价 while(1))。
二、常见的遍历模式
正着走(0 到 n-1):
c
int arr[5] = {1, 2, 3, 4, 5};
for (int i = 0; i < 5; i++) {
printf("%d\n", arr[i]);
}倒着走(n-1 到 0):
c
for (int i = 4; i >= 0; i--) { // 有符号下标,没问题
printf("%d\n", arr[i]);
}累加模式(累积器):
c
int sum = 0;
for (int i = 1; i <= 100; i++) {
sum += i;
}
printf("%d\n", sum); // 5050两个注意:
- 循环下标用
int。用size_t(无符号)倒着走会踩有符号与无符号的死循环坑; - 条件里比较的边界:
i < n比i <= n-1更不易错,且能让编译器做强度削减优化。
三、循环里的变量作用域
C99 起可以在 for 里声明下标变量,它的作用域就是这个循环:
c
for (int i = 0; i < 10; i++) { ... }
// 这里 i 不存在了!好处:循环用完的下标不会污染外层作用域,也不会和外面同名变量冲突。老代码(C89)必须在外面声明:
c
int i;
for (i = 0; i < 10; i++) { ... }
// 循环结束 i 还在新代码用 C99 风格(for (int i = ...)),本站示例统一这种写法。
四、for vs while
| 维度 | for | while |
|---|---|---|
| 结构 | 初始化/条件/更新集中一处 | 只有条件 |
| 适用 | 遍历次数已知 | 次数未知(等输入、等事件) |
| 可读性 | 三要素一目了然 | 更新可能在循环体里 |
判断标准很简单:循环"三要素"是否齐整。齐整用 for,不齐整用 while。while 的细节见下一篇 while 与 do-while。
五、循环与性能:本站的主线
为什么性能文档总盯着循环?看一段典型的"低效"代码:
c
int total = 0;
for (int i = 0; i < 1000000; i++) {
total += i;
}-O0 下这是一百万次 add;-O2 下编译器可能算都不算直接填结果(编译优化行为)。中间还有缓存、分支预测、向量化(SIMD)一系列机制。本站的 demos/cpu-demo 就是专门演示"循环里藏着的优化陷阱"。学到高手层以后,看循环会带着性能的眼镜。
六、常见坑对照
| 坑 | 现象 | 对策 |
|---|---|---|
下标用 size_t 倒着走 | 死循环 | 用 int |
条件写反 i > 0 当 i < n | 循环不执行 | 想清楚边界 |
| 循环里忘更新 | 死循环 | 三要素齐整 |
| 在循环里反复调用重函数 | 性能差 | 提到循环外(见下) |
= 当 == 在条件里 | 死循环或恒真 | 开 -Wall |
一个常见性能优化:循环不变的计算提到外面:
c
int len = strlen(s); // 提到循环外!
for (int i = 0; i < len; i++) {
// 每轮循环 strlen 都会重跑一遍(如果写 strlen(s))
}七、与本站主线衔接
- 循环的指令级形态(
cmp+jle跳回),见与汇编、性能剖析衔接; - 循环优化(循环展开、向量化、强度削减),见专家层编译优化行为;
- 实战演示循环被
-O2消除,见demos/cpu-demo。
一句话总结
for = 初始化 + 条件 + 更新三件套,按"判断→体→更新"循环;下标用 int、i < n 作条件、循环内变量 C99 风格声明;循环是性能剖析的第一现场,优化从把重计算移出循环开始。