7. 流程控制之if语句:单分支、双分支、多分支if-else if-else,嵌套if
说实话,C语言的流程控制里,if 语句是我用得最多的一个。没有之一。
你想想看,程序说白了就是「在什么条件下做什么事」。温度高了就开风扇,用户按了按钮就响应,数据校验失败就报错——这些全是 if 的活儿。
我刚开始写嵌入式程序那会儿,觉得 if 太简单了,不就是判断真假吗?后来踩了几个坑才明白,if 语句的写法、结构、嵌套深度,直接决定了代码是「能跑」还是「好维护」。
今天咱们就把 if 的四种形态彻底讲透。
7.1 单分支 if:最简单的判断
单分支 if 的结构就一句话:如果条件成立,就执行里面的代码;不成立,就跳过。
if (条件表达式) {
// 条件为真时执行的代码
}
举个例子。我在做温控项目时,经常要判断温度是否超限:
int temperature = 85;
if (temperature > 80) {
printf("温度过高,启动风扇!\n");
}
这里 temperature > 80 是条件表达式。85 大于 80,结果为真,所以会打印提示。
0(假)或 非0(真)。C语言里,任何非零值都视为真。所以 if (1) 永远成立,if (0) 永远不成立。
单分支的适用场景很明确:只需要在某个条件满足时做一件事,其他情况什么都不做。比如日志记录、阈值告警、调试开关。
7.2 双分支 if-else:二选一
双分支就是「要么A,要么B」。条件成立走 if,不成立走 else。
if (条件表达式) {
// 条件为真
} else {
// 条件为假
}
我举个例子。判断一个数是奇数还是偶数:
int num = 7;
if (num % 2 == 0) {
printf("%d 是偶数\n", num);
} else {
printf("%d 是奇数\n", num);
}
这里 num % 2 == 0 为假,所以走 else 分支,输出「7 是奇数」。
if 和 else 是互斥的。程序只会执行其中一个分支,不会两个都执行。
我曾经在项目里见过有人把 if-else 写成两个独立的 if,结果两个条件都满足时,两段代码都执行了。嗯,那 bug 查了我一下午。
7.3 多分支 if-else if-else:多个条件排队
现实中的判断往往不止两个选项。比如成绩等级:90分以上是A,80分以上是B,70分以上是C,60分以上是D,不及格是E。
这时候就需要 if-else if-else 结构:
if (条件1) {
// 条件1成立
} else if (条件2) {
// 条件1不成立,条件2成立
} else if (条件3) {
// 条件1、2都不成立,条件3成立
} else {
// 以上条件都不成立
}
看一个实际例子:
int score = 85;
if (score >= 90) {
printf("等级:A\n");
} else if (score >= 80) {
printf("等级:B\n");
} else if (score >= 70) {
printf("等级:C\n");
} else if (score >= 60) {
printf("等级:D\n");
} else {
printf("等级:E(不及格)\n");
}
85 分满足 score >= 80,所以输出「等级:B」。后面的条件不会再判断了。
else if 和 else 都会被跳过。所以条件的顺序很重要。如果把 score >= 80 写在 score >= 90 前面,那 95 分也会被判定为B,因为第一个条件就成立了。
我个人习惯把最严格的条件放在最前面,这样逻辑清晰,不容易漏判。
7.4 嵌套 if:条件里面套条件
有时候一个条件不够,需要在条件成立后,再做更细的判断。这就是嵌套 if。
if (条件1) {
if (条件2) {
// 条件1和条件2都成立
} else {
// 条件1成立,条件2不成立
}
} else {
// 条件1不成立
}
我在做嵌入式设备时,经常要判断「设备是否在线」和「数据是否有效」两个条件:
int device_online = 1;
int data_valid = 0;
if (device_online) {
if (data_valid) {
printf("设备在线,数据有效,开始处理\n");
} else {
printf("设备在线,但数据无效,等待重传\n");
}
} else {
printf("设备离线,无法通信\n");
}
嵌套 if 的好处是逻辑层次分明。但要注意:嵌套层数不要太深。我见过有人嵌套了七八层,代码缩进都快到屏幕右边了。那种代码,别说别人看不懂,过两周自己都看不懂。
switch 语句或者把内层逻辑封装成函数。代码是写给人看的,不是写给编译器看的。
7.5 知识体系总览
下面这张图把 if 语句的四种形态和它们的关系画出来了。你可以对照着看,心里有个整体框架。
7.6 避坑指南
讲完四种形态,我再分享几个实际开发中容易踩的坑。这些都是我亲身经历过的。
- 分号问题:我曾经在
if后面不小心加了个分号,写成if (条件);。结果条件判断完,后面的代码块永远执行。因为分号表示空语句,if管的是那个空语句,后面的代码块跟if没关系了。 - 赋值 vs 等于:
if (x = 5)是赋值,不是判断。赋值表达式的结果是赋的值,5 是非零,所以永远为真。正确的写法是if (x == 5)。我建议把常量写在左边:if (5 == x),这样万一写成=,编译器会报错。 - else 的匹配:嵌套
if时,else总是与最近的if匹配。如果不确定,加花括号明确范围。
- 单分支:一个条件,做一件事
- 双分支:二选一,互斥执行
- 多分支:多个条件排队,命中即停
- 嵌套:条件里套条件,注意深度
好了,if 语句就讲到这里。你把这些代码自己敲一遍,跑一跑,感受一下不同分支的执行流程。代码这东西,光看是学不会的。