switch 语句是一种多路分支控制结构,它允许一个变量或表达式与一系列值进行比较,并根据匹配的值执行相应的代码块,它可以看作是 if-else if-else 链式判断的一种更清晰、更高效的替代方案,特别是在处理多个离散值的情况下。

(图片来源网络,侵删)
基本语法
switch 语句的基本结构如下:
switch (expression) {
case constant1:
// 当 expression 的值等于 constant1 时,执行这里的代码
break;
case constant2:
// 当 expression 的值等于 constant2 时,执行这里的代码
break;
case constant3:
// 当 expression 的值等于 constant3 时,执行这里的代码
break;
default:
// expression 的值与任何一个 case 都不匹配,执行这里的代码
break;
}
工作原理
switch 语句的执行流程非常关键,理解了它,就能避免很多常见的错误:
- 计算表达式:程序首先计算
switch后面的expression的值。 - 寻找匹配项:程序将这个计算结果与每个
case标签后面的constant(常量)进行比较。 - 执行匹配分支:
- 如果找到了一个匹配的
case,程序就从该case的代码块开始执行。 - 关键点:一旦开始执行,程序会顺序执行该
case以及之后所有case中的代码,直到遇到break语句或switch语句的结束大括号 为止,这被称为“贯穿”(fall-through)。
- 如果找到了一个匹配的
- 处理默认情况:
expression的值与所有case的常量都不匹配,程序就会跳过所有case代码块,直接执行default标签下的代码。default部分是可选的,但如果省略且没有匹配项,则switch语句不执行任何操作。
关键规则和注意事项
a. expression 的数据类型
switch 后面的 expression 必须是一个整型表达式,这意味着它可以有以下类型:
intchar(本质上是 1 字节的整型)shortlonglong longenum(枚举类型)- 不能是:
float,double,bool, 或字符串等非整型类型。
b. case 标签的值
- 每个
case后面的constant必须是一个常量或常量表达式(10, 'A',5*2)。不能是变量。 - 在同一个
switch语句中,所有case标签的值必须是唯一的,不能重复。
c. break 语句的重要性
break 语句用于终止 switch 语句的执行,并跳出 switch 结构,如果不使用 break,就会发生“贯穿”现象。

(图片来源网络,侵删)
示例:贯穿现象
#include <stdio.h>
int main() {
int grade = 'B'; // 字符 'B' 的 ASCII 码是 66
switch (grade) {
case 'A':
printf("Excellent!\n");
break; // 如果匹配 'A',执行完这句就退出 switch
case 'B':
printf("Good job!\n");
// 没有 break,程序会继续执行下一个 case
case 'C':
printf("You passed.\n");
// 没有 break,程序会继续执行下一个 case
case 'D':
printf("You should work harder.\n");
break;
default:
printf("Invalid grade.\n");
break;
}
return 0;
}
输出结果:
Good job!
You passed.
You should work harder.
因为 grade 的值是 'B',程序从 case 'B': 开始执行,打印 "Good job!",因为没有 break,它继续向下执行 case 'C': 和 case 'D': 的代码,直到遇到 case 'D': 中的 break 才退出。
d. default
default 是可选的,但强烈建议使用,以处理所有未预料到的情况,使代码更健壮。
default 的位置可以是任意的,但通常放在最后,这样逻辑上更清晰。
switch vs. if-else if-else
特性
switch 语句
if-else if-else 语句
判断条件
只能判断离散的、确定的值
可以判断范围、表达式、条件
数据类型
限制为整型
几乎所有数据类型(int, float, char, string 等)
执行效率
对于多分支情况,通常比 if-else 链更高效(编译器可能优化为跳转表)
效率取决于分支的数量,但通常不如 switch
代码可读性
当分支很多且都是简单值比较时,代码结构更清晰
当分支逻辑复杂或有范围判断时,可读性更好
“贯穿”特性
有“贯穿”特性,有时是缺点,但有时也很有用(见下文)
没有贯穿特性,每个 else if 都是独立的
实践示例
示例 1:标准用法(带 break)
#include <stdio.h>
int main() {
int day = 3;
switch (day) {
case 1:
printf("Monday\n");
break;
case 2:
printf("Tuesday\n");
break;
case 3:
printf("Wednesday\n");
break;
case 4:
printf("Thursday\n");
break;
case 5:
printf("Friday\n");
break;
case 6:
printf("Saturday\n");
break;
case 7:
printf("Sunday\n");
break;
default:
printf("Invalid day number\n");
break;
}
return 0;
}
输出:
(图片来源网络,侵删)
Wednesday
示例 2:利用“贯穿”特性
假设我们想根据分数评定等级,A (90-100), B (80-89), C (70-79), D (60-69), F (<60),我们可以利用 switch 的特性简化代码。
#include <stdio.h>
int main() {
int score = 85;
// 注意:这里判断的是 score / 10 的商
switch (score / 10) {
case 10:
case 9:
printf("Grade: A\n");
break;
case 8:
printf("Grade: B\n");
break;
case 7:
printf("Grade: C\n");
break;
case 6:
printf("Grade: D\n");
break;
default: // 包含了 0-5 的情况
printf("Grade: F\n");
break;
}
return 0;
}
输出:
Grade: B
这里 case 10: 和 case 9: 共享了同一段代码,因为 score / 10 的值无论是 10 还是 9,都应该评为 'A',这是“贯穿”特性一个非常好的应用场景。
示例 3:switch 中使用 char
#include <stdio.h>
int main() {
char op = '+';
int a = 10, b = 5, result;
switch (op) {
case '+':
result = a + b;
printf("Result: %d\n", result);
break;
case '-':
result = a - b;
printf("Result: %d\n", result);
break;
case '*':
result = a * b;
printf("Result: %d\n", result);
break;
case '/':
if (b != 0) {
result = a / b;
printf("Result: %d\n", result);
} else {
printf("Error: Division by zero!\n");
}
break;
default:
printf("Invalid operator!\n");
break;
}
return 0;
}
输出:
Result: 15
- 何时使用
switch? 当你需要根据一个变量的多个离散整数值来执行不同的代码块时,switch 是比 if-else if-else 更清晰、更高效的选择。
- 核心要点:
switch 的表达式必须是整型。
case 的值必须是唯一的常量。
break 是防止“贯穿”的关键,除非你特意利用贯穿特性。
default 用于处理所有不匹配的情况,是良好的编程习惯。
- 高级用法:巧妙利用“贯穿”特性可以简化对多个范围或共享代码块的处理。
default是可选的,但强烈建议使用,以处理所有未预料到的情况,使代码更健壮。default的位置可以是任意的,但通常放在最后,这样逻辑上更清晰。
switch vs. if-else if-else
| 特性 | switch 语句 |
if-else if-else 语句 |
|---|---|---|
| 判断条件 | 只能判断离散的、确定的值 | 可以判断范围、表达式、条件 |
| 数据类型 | 限制为整型 | 几乎所有数据类型(int, float, char, string 等) |
| 执行效率 | 对于多分支情况,通常比 if-else 链更高效(编译器可能优化为跳转表) |
效率取决于分支的数量,但通常不如 switch |
| 代码可读性 | 当分支很多且都是简单值比较时,代码结构更清晰 | 当分支逻辑复杂或有范围判断时,可读性更好 |
| “贯穿”特性 | 有“贯穿”特性,有时是缺点,但有时也很有用(见下文) | 没有贯穿特性,每个 else if 都是独立的 |
实践示例
示例 1:标准用法(带 break)
#include <stdio.h>
int main() {
int day = 3;
switch (day) {
case 1:
printf("Monday\n");
break;
case 2:
printf("Tuesday\n");
break;
case 3:
printf("Wednesday\n");
break;
case 4:
printf("Thursday\n");
break;
case 5:
printf("Friday\n");
break;
case 6:
printf("Saturday\n");
break;
case 7:
printf("Sunday\n");
break;
default:
printf("Invalid day number\n");
break;
}
return 0;
}
输出:

(图片来源网络,侵删)
Wednesday
示例 2:利用“贯穿”特性
假设我们想根据分数评定等级,A (90-100), B (80-89), C (70-79), D (60-69), F (<60),我们可以利用 switch 的特性简化代码。
#include <stdio.h>
int main() {
int score = 85;
// 注意:这里判断的是 score / 10 的商
switch (score / 10) {
case 10:
case 9:
printf("Grade: A\n");
break;
case 8:
printf("Grade: B\n");
break;
case 7:
printf("Grade: C\n");
break;
case 6:
printf("Grade: D\n");
break;
default: // 包含了 0-5 的情况
printf("Grade: F\n");
break;
}
return 0;
}
输出:
Grade: B
这里 case 10: 和 case 9: 共享了同一段代码,因为 score / 10 的值无论是 10 还是 9,都应该评为 'A',这是“贯穿”特性一个非常好的应用场景。
示例 3:switch 中使用 char
#include <stdio.h>
int main() {
char op = '+';
int a = 10, b = 5, result;
switch (op) {
case '+':
result = a + b;
printf("Result: %d\n", result);
break;
case '-':
result = a - b;
printf("Result: %d\n", result);
break;
case '*':
result = a * b;
printf("Result: %d\n", result);
break;
case '/':
if (b != 0) {
result = a / b;
printf("Result: %d\n", result);
} else {
printf("Error: Division by zero!\n");
}
break;
default:
printf("Invalid operator!\n");
break;
}
return 0;
}
输出:
Result: 15
- 何时使用
switch? 当你需要根据一个变量的多个离散整数值来执行不同的代码块时,switch是比if-else if-else更清晰、更高效的选择。 - 核心要点:
switch的表达式必须是整型。case的值必须是唯一的常量。break是防止“贯穿”的关键,除非你特意利用贯穿特性。default用于处理所有不匹配的情况,是良好的编程习惯。
- 高级用法:巧妙利用“贯穿”特性可以简化对多个范围或共享代码块的处理。
