判断语句(Conditional Statements)
判断语句让程序根据条件选择不同的执行路径,是实现"决策逻辑"的基础。C 语言提供 if-else 和 switch-case 两种机制。
1. 为什么需要判断
没有判断,程序只能按固定顺序执行。判断赋予了程序"根据数据做不同事情"的能力:
用户登录? ──是──→ 显示主页
│
否
│
└──────→ 显示登录界面
2. if 语句
2.1 基本形式
if (条件) {
// 条件为真时执行
}
int temperature = 35;
if (temperature > 30) {
printf("天气炎热,开启制冷\n");
}
2.2 if-else
if (temperature > 30) {
printf("开启制冷\n");
} else {
printf("制冷未开启\n");
}
2.3 if-else if-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("等级:F\n");
}
2.4 条件表达式
在 C 语言中,条件的真假判定遵循简单规则:
| 条件值 | 判定 |
|---|---|
0 |
假(false) |
非零(1、-1、42 等) |
真(true) |
int flag = 1;
if (flag) { // 等价于 if (flag != 0)
printf("flag 为真\n");
}
int* ptr = NULL;
if (!ptr) { // 等价于 if (ptr == NULL)
printf("指针为空\n");
}
2.5 省略大括号的风险
// 危险写法——只有紧邻的一行属于 if
if (score > 60)
printf("及格\n");
printf("恭喜\n"); // 这行不论条件真假都会执行!
// 安全写法——始终使用大括号
if (score > 60) {
printf("及格\n");
printf("恭喜\n");
}
建议:即使只有一行语句,也保留大括号。这可以避免后续添加代码时无意中破坏逻辑。
3. switch-case 语句
当一个变量需要与多个离散值比较时,switch 比一连串 if-else if 更清晰。
3.1 基本形式
int day = 3;
switch (day) {
case 1:
printf("星期一\n");
break;
case 2:
printf("星期二\n");
break;
case 3:
printf("星期三\n");
break;
case 4:
printf("星期四\n");
break;
case 5:
printf("星期五\n");
break;
default:
printf("周末\n");
break;
}
3.2 break 的作用
break 跳出当前 switch 块。如果遗漏 break,程序会穿透(fall-through)到下一个 case 继续执行:
int n = 1;
switch (n) {
case 1:
printf("一\n");
// 没有 break → 继续执行 case 2
case 2:
printf("二\n");
break;
}
// 输出:
// 一
// 二
3.3 有意使用穿透
有时穿透是设计意图而非错误:
char grade = 'B';
switch (grade) {
case 'A':
case 'B':
case 'C':
printf("通过\n"); // A、B、C 共用同一处理
break;
case 'D':
case 'F':
printf("未通过\n");
break;
}
多个 case 空标签叠放表示它们共享后续代码,这种写法比逐个 if 更简洁。
3.4 switch 的限制
| 限制 | 说明 |
|---|---|
| 表达式必须是整数类型 | int、char、enum 等;float/double 不可用 |
case 值必须是常量 |
不能是变量或表达式 |
| 不会自动跳出 | 必须写 break,否则会穿透 |
4. 嵌套判断
int year = 2024;
if (year % 4 == 0) {
if (year % 100 == 0) {
if (year % 400 == 0) {
printf("%d 是闰年\n", year);
} else {
printf("%d 不是闰年\n", year);
}
} else {
printf("%d 是闰年\n", year);
}
} else {
printf("%d 不是闰年\n", year);
}
嵌套层级超过 3 层时,可读性急剧下降。此时应拆分为独立函数或合并条件:
// 合并后的闰年判断(更清晰)
if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)) {
printf("%d 是闰年\n", year);
} else {
printf("%d 不是闰年\n", year);
}
5. if vs switch 选择指南
| 场景 | 推荐 | 原因 |
|---|---|---|
条件涉及范围(x > 10) |
if-else if |
switch 只支持等值比较 |
| 与多个离散常量比较 | switch |
结构更清晰,编译器可能优化为跳转表 |
| 条件涉及多个变量 | if-else if |
switch 只能基于一个表达式 |
| 分支数 ≤ 3 | if-else |
简单场景不必引入 switch 的语法开销 |
| 浮点数比较 | if-else if |
switch 不支持 float/double |
6. 条件运算符的替代用法
对于简单的二选一赋值,条件运算符(?:)比 if-else 更紧凑:
// 用 if-else
int max;
if (a > b) {
max = a;
} else {
max = b;
}
// 用条件运算符(更简洁)
int max = (a > b) ? a : b;
但避免嵌套使用:
// 不推荐:嵌套条件运算符难读
int result = (a > b) ? ((a > c) ? a : c) : ((b > c) ? b : c);
// 推荐:拆分为 if-else if 或函数
int result;
if (a > b && a > c) result = a;
else if (b > a && b > c) result = b;
else result = c;
7. 常见错误
| 错误 | 原因 | 正确写法 |
|---|---|---|
if (x = 5) |
用了赋值 = 而非比较 == |
if (x == 5) |
if (0 < x < 10) |
数学写法在 C 中不合法,会先算 0 < x 得到 0 或 1,再与 10 比较 |
if (x > 0 && x < 10) |
switch 遗漏 break |
导致了非预期的穿透 | 每个 case 后确保有 break |
case 后使用变量 |
case n: 中 n 必须是常量 |
改用 if-else if |
多余的 ; |
if (x > 0); 后面的分号是一个空语句 |
删除多余分号 |
8. 总结
| 要点 | 说明 |
|---|---|
if-else 是通用判断 |
支持任意条件表达式,包括范围和逻辑组合 |
switch 适合等值多分支 |
表达式必须是整数类型,case 值必须是常量 |
不要忘记 break |
switch 中遗漏 break 会导致穿透 |
| 始终使用大括号 | 即使单行语句也保留,防止后续修改引入 bug |
= 是赋值,== 是比较 |
编译器的警告可能救你一次 |
| 深度嵌套应重构 | 超过 3 层考虑提取函数或合并条件 |
作者: Qing | 修改日期: 2026-07-18