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 是奇数」。

重点:双分支的 ifelse 是互斥的。程序只会执行其中一个分支,不会两个都执行。

我曾经在项目里见过有人把 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 ifelse 都会被跳过。所以条件的顺序很重要。如果把 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 语句的四种形态和它们的关系画出来了。你可以对照着看,心里有个整体框架。

if 语句四种形态 if 语句 单分支 if 双分支 if-else 多分支 if-else if 嵌套 if 条件成立时执行 不成立则跳过 二选一,互斥执行 条件真走if,假走else 多个条件依次判断 命中一个即停止 条件内再套条件 注意嵌套深度不超过3层

7.6 避坑指南

讲完四种形态,我再分享几个实际开发中容易踩的坑。这些都是我亲身经历过的。

  • 分号问题:我曾经在 if 后面不小心加了个分号,写成 if (条件);。结果条件判断完,后面的代码块永远执行。因为分号表示空语句,if 管的是那个空语句,后面的代码块跟 if 没关系了。
  • 赋值 vs 等于:if (x = 5) 是赋值,不是判断。赋值表达式的结果是赋的值,5 是非零,所以永远为真。正确的写法是 if (x == 5)。我建议把常量写在左边:if (5 == x),这样万一写成 =,编译器会报错。
  • else 的匹配:嵌套 if 时,else 总是与最近的 if 匹配。如果不确定,加花括号明确范围。
核心总结:
  • 单分支:一个条件,做一件事
  • 双分支:二选一,互斥执行
  • 多分支:多个条件排队,命中即停
  • 嵌套:条件里套条件,注意深度

好了,if 语句就讲到这里。你把这些代码自己敲一遍,跑一跑,感受一下不同分支的执行流程。代码这东西,光看是学不会的。