5.3 for
for 把“初始化、条件判断、步进表达式”集中写在一行,是 C 中最常见的计数循环结构。它与 while 可以互相改写,但在边界控制上通常更紧凑。
1. 基本语法
c
for (init; condition; step) {
statement;
}1
2
3
2
3
执行顺序是:先执行 init,再判断 condition;若条件非零就执行循环体,然后执行 step,再回到条件判断。
2. 示例
c
#include <stdio.h>
int main(void) {
int sum = 0;
for (int i = 1; i <= 100; ++i) {
sum += i;
}
printf("%d\n", sum);
return 0;
}1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
输出:
bash
5050
这里把循环控制对象 i 的生命周期限制在 for 语句内部,减少了作用域泄露。
3. 常见变体
for (;;) 表示无限循环;三个表达式都可以省略,但分号必须保留。省略任何一项都应有明确意图,否则会降低可读性。
4. 逆序循环的边界
for 写逆序遍历时,若索引类型是无符号整型,要特别注意下溢边界。下面这种写法更稳妥:
c
#include <stddef.h>
void visit_reverse(const int *a, size_t n) {
for (size_t i = n; i > 0; --i) {
int v = a[i - 1];
(void)v;
}
}1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
它通过 i > 0 保证 i - 1 总是有效索引,避免把无符号对象减到极大值后继续循环。
5. 多控制表达式写法
for 还可以在初始化和步进位置维护多个控制对象。这种写法在双指针扫描、窗口移动等场景中很常见,但要保证每个控制对象的职责清晰。
c
#include <stdio.h>
int main(void) {
for (int left = 0, right = 4; left <= right; ++left, --right) {
printf("(%d, %d)\n", left, right);
}
return 0;
}1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
输出:
bash
(0, 4) (1, 3) (2, 2)
当控制对象过多时,建议提炼出辅助函数,避免把 for 头部堆成难读表达式。
6. continue 与步进表达式
for 中执行 continue 时,不会直接回到条件判断,而是先执行 step,再进入下一轮条件检查。这个语义在“步进里包含资源更新”时尤为关键:若你把关键更新动作只写在循环体尾部,continue 可能绕过它;把每轮都必须执行的推进动作放在 step 中,路径会更稳定。