5. 流程控制(一):if语句、if-else语句、else if阶梯、switch-case语句、条件运算符(三目运算符)

流程控制,说白了就是让程序学会「看情况办事」。

我刚开始学C语言时,觉得这玩意儿不就是判断一下嘛,有啥好讲的?后来做项目多了才发现,流程控制写得不好,代码就像一团乱麻。你想想看,一个函数里嵌套七八层if,调试的时候简直想砸电脑。

今天咱们就把流程控制的基础打牢。嗯,先从最简单的说起。

5.1 if语句:最简单的判断

if语句就像你过马路时的决定——绿灯走,红灯停。在C语言里,它的写法是这样的:

if (条件表达式) {
    // 条件为真时执行的代码
}

注意,这里的「条件表达式」必须是一个能得出真或假的东西。C语言里,0代表假,非0代表真。这个细节我当年栽过跟头——有一次把一个赋值表达式 = 写成了比较 ==,结果程序永远进不了那个分支。

⚠️ 我曾经踩过的坑: 在if条件里误用 = 代替 ==。编译器不会报错,但逻辑全乱套。我的习惯是:如果判断一个变量是否等于某个常量,我会把常量写在左边,比如 if (5 == x),这样万一写成 =,编译器会报错。

来看个实际例子:

int temperature = 38;
if (temperature > 37) {
    printf("体温偏高,建议复查\n");
}

这段代码很简单——体温超过37度就打印提示。但实际项目中,我很少只用单个if。为什么?因为现实世界很少只有「是」和「否」两种情况。

5.2 if-else语句:二选一

if-else就是「要么A,要么B」。没有中间地带。

if (score >= 60) {
    printf("及格了\n");
} else {
    printf("不及格\n");
}

我在做嵌入式设备时,经常用这种结构来判断传感器数据是否在正常范围内。比如检测电机温度:

if (motor_temp < 85) {
    motor_status = NORMAL;
} else {
    motor_status = OVERHEAT;
    emergency_stop();
}

这里有个小技巧:把大概率发生的情况放在if分支。因为CPU的分支预测机制对「常见路径」更友好,能提升一点点性能。虽然现代编译器优化很强,但这个习惯我一直保留着。

5.3 else if阶梯:多路分支

当判断条件超过两个时,else if就派上用场了。它像是一个「从上到下」的筛选过程。

if (score >= 90) {
    grade = 'A';
} else if (score >= 80) {
    grade = 'B';
} else if (score >= 70) {
    grade = 'C';
} else if (score >= 60) {
    grade = 'D';
} else {
    grade = 'F';
}

我个人习惯在写else if时,把最严格的条件放在最前面。为什么?因为一旦匹配成功,后面的条件就不会再判断了。这样可以减少不必要的比较。

💡 实战建议: 在嵌入式系统中,else if链不宜过长。我一般控制在5层以内。如果超过5层,我会考虑用switch-case或者查表法来替代。代码可读性比那一点点性能更重要。

5.4 switch-case语句:精准匹配

switch-case适合做「等值判断」。它不像else if那样可以判断范围,但它胜在清晰、高效。

switch (command) {
    case 0x01:
        start_motor();
        break;
    case 0x02:
        stop_motor();
        break;
    case 0x03:
        set_speed(100);
        break;
    default:
        printf("未知指令\n");
        break;
}

这里有个关键点——别忘了break。我见过太多新手因为漏掉break导致程序「穿透」到下一个case。这在某些场景下是有意为之,但大多数时候是bug。

⚠️ 我曾经踩过的坑: 有一次写通信协议解析,case 0x01后面忘了加break,结果执行完case 0x01的逻辑后,又跑进了case 0x02。排查了整整一个下午才发现。从那以后,我写switch-case必先写break,再写逻辑代码。

switch-case的case值必须是整型常量。字符也可以,因为字符本质上是ASCII码。但浮点数不行,这点要注意。

5.5 条件运算符(三目运算符)

三目运算符是C语言里唯一一个需要三个操作数的运算符。它的格式是:

表达式1 ? 表达式2 : 表达式3

如果表达式1为真,整个表达式的值就是表达式2的值;否则是表达式3的值。

举个例子:

int max = (a > b) ? a : b;

这比写if-else要简洁得多。但我建议你只在简单赋值场景下使用。如果逻辑复杂,还是老老实实写if-else吧。

💡 我的使用原则: 三目运算符嵌套不超过一层。比如 a ? b : (c ? d : e) 勉强能接受,再深就影响阅读了。代码是写给人看的,不是写给编译器看的。

5.6 知识体系总览

下面这张图把本章的知识点串起来了。你可以把它当作一个「决策树」来看:

流程控制(一)知识体系 流程控制 if 语句 if-else 语句 else if 阶梯 switch-case 条件为真时执行 二选一分支 多路范围判断 等值匹配 三目运算符 简洁赋值场景 核心原则:清晰 > 简洁 > 性能

5.7 几种语句的对比

为了让你更直观地理解它们的区别,我整理了一张对比表:

语句类型 适用场景 优点 缺点
if 单一条件判断 简单直接 无法处理else情况
if-else 二选一 覆盖所有情况 分支多时代码冗长
else if 多路范围判断 灵活,支持范围 嵌套过深影响可读性
switch-case 等值匹配 结构清晰,效率高 只能判断整型常量
三目运算符 简单赋值 代码简洁 嵌套复杂时难读

5.8 实战中的选择建议

说了这么多,到底该用哪个?我的经验是:

  • 判断范围(比如分数等级、温度区间)→ 用else if
  • 判断具体值(比如按键值、指令码)→ 用switch-case
  • 简单二选一(比如取最大值)→ 用三目运算符
  • 复杂逻辑(多个条件组合)→ 用if-else,必要时拆成多个函数

📌 核心原则: 代码首先是给人读的,其次才是给机器执行的。不要为了炫技写出让人看不懂的代码。我见过有人把三目运算符嵌套了五层,美其名曰「一行搞定」。说实话,这种代码我宁愿重写也不愿意去调试。

好了,流程控制的第一部分就到这里。这些基础语句看似简单,但用好了能让你的代码既清晰又高效。下一章咱们继续聊循环控制——for、while、do-while,到时候再分享一些我在实际项目中遇到的坑。


公众号:蓝海资料掘金营,微信deep3321