第31章 do-while 循环:它和 while 循环的根本区别
说实话,很多学C语言的朋友,写了好几年代码,对 do-while 还是有点「敬而远之」。我见过不少项目里,明明用 do-while 更合适,大家却硬生生写成 while + 额外标记变量。为什么?因为没搞懂它俩的根本区别。
今天咱们就把这个事彻底说清楚。
31.1 先看一个最直观的例子
先上代码,你感受一下:
// while 循环
int x = 10;
while (x < 5) {
printf("x = %d\n", x);
x++;
}
// 输出:无任何输出
// do-while 循环
int y = 10;
do {
printf("y = %d\n", y);
y++;
} while (y < 5);
// 输出:y = 10
看到了吗?条件不满足时,while 一次都不执行,do-while 至少执行一次。
这就是根本区别——判断时机不同。
- while:先判断,后执行。条件为假,循环体直接跳过。
- do-while:先执行,后判断。循环体至少跑一次。
核心一句话:do-while 保证循环体至少执行一次,while 不保证。
31.2 什么时候该用 do-while?
我个人习惯是:当循环体必须执行一次,且执行结果影响判断条件时,用 do-while。
举个实际例子。我在做嵌入式项目时,经常需要等待某个硬件寄存器变成特定值。比如等待 ADC 转换完成:
// 等待 ADC 转换完成
do {
status = read_adc_status(); // 先读一次状态
} while (status & ADC_BUSY); // 如果还在忙,继续等
为什么这里用 do-while?因为 你总得先发起一次转换,才能知道它完没完成。如果用 while,你得在循环外面先读一次状态,代码就多了一行冗余:
status = read_adc_status(); // 冗余的第一次读取
while (status & ADC_BUSY) {
status = read_adc_status();
}
你看,do-while 把第一次读取自然地放进了循环体里,代码更干净、更符合逻辑。
31.3 另一个经典场景:用户输入验证
我记得有一次写一个菜单程序,要求用户输入 1-3 之间的数字。用 do-while 简直不要太舒服:
int choice;
do {
printf("请选择 (1-3): ");
scanf("%d", &choice);
} while (choice < 1 || choice > 3);
用户至少得输入一次,然后根据输入决定要不要继续提示。如果用 while,你得先给 choice 赋一个非法值才能进入循环,多此一举。
小技巧:凡是「先做一次,再决定是否继续」的场景,优先考虑 do-while。比如:读取文件直到末尾、发送命令直到收到响应、轮询设备状态等。
31.4 两者的流程图对比
下面这张 SVG 图,把 while 和 do-while 的执行流程画得清清楚楚。你看一眼就明白了。
从图上可以清楚看到:while 是先经过判断菱形再进循环体,do-while 是先执行循环体再判断。这个顺序差异,决定了它们的使用场景完全不同。
31.5 避坑指南
我曾经在一个通信协议栈里犯过这个错:用 while 循环等待接收缓冲区非空,结果第一次调用时缓冲区本来就是空的,循环直接跳过,导致后续逻辑全部跑飞。后来改成 do-while,问题立刻解决。
这里总结几个常见的坑:
- 不要忘了 do-while 后面的分号。while 后面没有分号,do-while 的 while 后面有分号。这个我见过无数人漏掉。
- do-while 的循环体即使只有一条语句,也建议加花括号。虽然语法允许不加,但加了可读性更好,也避免以后扩展时出错。
- 注意 do-while 和 while 在逻辑上的等价转换。有时候你看到别人的代码用 while 实现了「至少执行一次」的效果,那多半是在循环外面先执行了一次——这种写法不如 do-while 直观。
31.6 什么时候用 while 而不是 do-while?
反过来想,什么时候 不该 用 do-while?
当循环体可能一次都不需要执行时,用 while。比如遍历一个可能为空的链表:
Node *p = head;
while (p != NULL) {
process(p);
p = p->next;
}
如果链表是空的,p 一开始就是 NULL,循环体一次都不执行——这正是我们想要的。如果用 do-while,就会先处理一个空节点,直接崩溃。
我的建议:写代码前先问自己一个问题——「这个循环体有没有可能一次都不该执行?」如果答案是「有可能」,用 while;如果答案是「必须至少执行一次」,用 do-while。
31.7 总结一下
| 对比项 | while | do-while |
|---|---|---|
| 判断时机 | 先判断,后执行 | 先执行,后判断 |
| 最少执行次数 | 0 次 | 1 次 |
| 典型场景 | 遍历链表、搜索数据 | 用户输入验证、硬件轮询 |
| 语法特点 | while 后无分号 | while 后有分号 |
说白了,do-while 就是 while 的「先干再说」版本。你想想看,生活中很多事情也是这个道理——先做一次尝试,再决定要不要继续。do-while 恰恰反映了这种思维模式。
嗯,这个区别其实很简单,但很多人就是没转过这个弯。希望今天讲完,你能彻底记住:do-while 保证至少执行一次,while 不保证。就这么简单。
公众号:蓝海资料掘金营,微信 deep3321