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; // 在 default 中不是必须的,因为它是最后一个分支
}
核心组成部分解析
-
switch (expression):expression是一个整型表达式,这意味着它可以是一个int、char、short、long等整型变量或结果。*浮点数(float,double)和字符串(`char)不能用于switch` 语句。**- 程序会计算这个表达式的值,然后与每个
case后面的常量进行比较。
-
case constant::constant必须是一个常量或常量表达式(如10, 'A',5*2)。不能是变量。case标签本身不会导致程序停止执行,如果匹配到某个case,程序会开始执行该case之后的代码,并且会继续向下执行,直到遇到一个break语句或者switch语句的结束大括号 ,这被称为“贯穿”(fall-through)。
-
break;:
(图片来源网络,侵删)break语句的作用是立即终止switch语句的执行,程序会跳转到switch语句后面的第一条语句继续执行。- 如果没有
break,程序会“贯穿”到下一个case块中执行,这通常是错误的,但有时也会被有意利用(见后面的例子)。
-
default::default是一个可选的“默认”分支。expression的值与任何一个case常量都不匹配,程序就会执行default分支中的代码。default分支可以放在switch语句的任何位置,但通常放在最后,逻辑上更清晰。
一个简单的例子
假设我们要根据一个学生的分数等级('A', 'B', 'C', 'D')来输出不同的评价。
#include <stdio.h>
int main() {
char grade = 'B';
switch (grade) {
case 'A':
printf("优秀!\n");
break;
case 'B':
printf("良好!\n");
break;
case 'C':
printf("及格,\n");
break;
case 'D':
printf("不及格,\n");
break;
default:
printf("无效的等级,\n");
break;
}
return 0;
}
执行流程:
grade的值是'B'。switch语句开始执行,将'B'与各个case的值进行比较。- 它发现
'B'与case 'B':匹配。 - 程序开始执行
case 'B':后面的代码:printf("良好!\n");。 - 接着遇到
break;语句,switch语句立即终止。 - 程序跳转到
return 0;并结束。
“贯穿”(Fall-through)现象
这是 switch 语句一个非常重要的特性。如果没有 break,程序会继续执行下一个 case 的代码。

(图片来源网络,侵删)
例子:
#include <stdio.h>
int main() {
int number = 2;
switch (number) {
case 1:
printf("数字是 1\n");
break;
case 2:
printf("数字是 2\n");
// 注意:这里没有 break
case 3:
printf("数字是 3\n");
break;
default:
printf("数字不在 1-3 范围内\n");
break;
}
return 0;
}
输出结果:
数字是 2
数字是 3
执行流程:
number是2。- 匹配到
case 2:,打印 "数字是 2"。 - 因为没有
break,程序不退出switch,而是继续向下执行。 - 它进入
case 3:块,打印 "数字是 3"。 - 遇到
break,退出switch。
何时利用贯穿?
一个常见的用途是,将多个 case 共享同一段代码。
#include <stdio.h>
int main() {
int month = 4;
switch (month) {
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
printf("这个月有 31 天,\n");
break;
case 4:
case 6:
case 9:
case 11:
printf("这个月有 30 天,\n");
break;
case 2:
printf("这个月可能是 28 或 29 天,\n");
break;
default:
printf("无效的月份,\n");
break;
}
return 0;
}
当 month 是 4, 6, 9, 11 中的任何一个时,都会执行 case 4: 的代码,然后因为没有 break,会依次“贯穿”到 case 6:, case 9:, case 11:,但它们也都没有 break,直到遇到 printf 语句并执行,最后在 break 处退出。
switch vs. if-else if-else
| 特性 | switch 语句 |
if-else if-else 语句 |
|---|---|---|
| 可读性 | 当检查同一个变量的多个离散值时,代码更清晰、更结构化。 | 当条件复杂、范围化或逻辑关系简单时,更直观。 |
| 数据类型 | 仅限整型 (int, char, enum 等)。 |
任何数据类型,可以比较浮点数、字符串等。 |
| 比较方式 | 仅进行相等性比较 ()。 | 可以进行任何比较 (, , >, <, >=, <=)。 |
| 执行效率 | 在某些情况下,编译器可以生成更高效的跳转表(jump table),性能可能优于一连串的 if-else 比较。 |
对于少量条件,效率很高,对于大量条件,可能比 switch 稍慢。 |
| 灵活性 | 较低,结构固定。 | 非常灵活,可以处理各种复杂的逻辑组合。 |
最佳实践和注意事项
- 总是为每个
case使用break,除非你明确地想要利用“贯穿”特性,忘记break是一个非常常见的错误。 - 使用
default分支,它可以作为一种“安全网”,处理所有未预料到的输入情况,使你的代码更健壮。 case标签必须是唯一的,你不能有两个case 1:。- 注意数据类型,确保
switch表达式和case常量的类型是兼容的整型。
switch 语句是 C 语言中一个强大且有用的控制流工具,特别适合处理基于单一整型变量的多路选择场景,理解其“贯穿”特性是掌握 switch 的关键,虽然 if-else if-else 更通用,但在特定情况下,switch 能提供更清晰、更高效的代码。
