switch-case 是一种多路分支控制结构,它允许一个变量或表达式在多个不同的值之间进行选择执行,可以把它想象成一个多向的开关,根据一个“开关值”来接通不同的“线路”(执行不同的代码块)。

基本语法结构
switch-case 语句的基本语法如下:
switch (expression) {
case constant-expression1:
// 当 expression 的值等于 constant-expression1 时,执行这里的代码
break; // 可选,用于跳出 switch
case constant-expression2:
// 当 expression 的值等于 constant-expression2 时,执行这里的代码
break; // 可选
case constant-expression3:
// 当 expression 的值等于 constant-expression3 时,执行这里的代码
break; // 可选
default:
// expression 的值不匹配任何一个 case,执行这里的代码
break; // 可选
}
语法详解
a. switch (expression)
expression:这是一个表达式,它的值会被计算出来。- 关键规则:
expression的结果类型必须是 整型(int,char,short,long等)或者 枚举类型。浮点型(如float,double)是不允许的。 - 程序会将这个表达式的值与后面
case标签中的值进行匹配。
b. case constant-expression:
constant-expression:这是一个常量表达式,这意味着它必须是一个固定的值,不能是变量。- 关键规则:每个
case标签的值必须是唯一的,不能有两个case使用相同的常量值。 - 当
switch的表达式值与某个case的值匹配时,程序会从该case的位置开始执行,并继续向下执行,直到遇到break语句或switch语句的结束大括号 。
c. break;
break语句的作用是立即终止switch语句的执行,并将程序控制权转移到switch语句后面的第一条语句。- 如果没有
break,程序会发生 “贯穿”(fall-through) 现象,即执行完一个case后,会继续执行下一个case的代码,直到遇到break或switch结束,这在某些情况下是有意为之的,但更多时候是忘记写break导致的逻辑错误。
d. default:
default是一个可选的分支,类似于if-else中的else。switch表达式的值没有匹配到任何一个case,那么程序就会执行default分支中的代码。default分支可以放在switch结构的任何位置(通常习惯放在最后),但从可读性角度,放在最后是最佳实践。
示例代码
示例 1:基本用法(带 break)
这是一个最常见、最标准的用法,每个 case 都有自己的 break。
#include <stdio.h>
int main() {
int day = 3;
char day_name;
switch (day) {
case 1:
day_name = 'M';
break;
case 2:
day_name = 'T';
break;
case 3:
day_name = 'W';
break;
case 4:
day_name = 'H';
break;
case 5:
day_name = 'F';
break;
default:
day_name = 'U'; // Unknown
break;
}
printf("Day name is: %c\n", day_name); // 输出: Day name is: W
return 0;
}
执行流程:
day的值是3。switch开始匹配。case 1(值为1) 不匹配。case 2(值为2) 不匹配。case 3(值为3) 匹配。- 程序执行
case 3中的代码:day_name = 'W';。 - 遇到
break;,switch语句立即结束。 - 程序跳转到
printf语句并打印结果。
示例 2:“贯穿”(Fall-through)现象
这个示例展示了当没有 break 时会发生什么。

#include <stdio.h>
int main() {
int score = 85;
char grade;
switch (score / 10) {
case 10:
case 9:
grade = 'A';
break;
case 8:
grade = 'B';
// 注意:这里没有 break!
case 7:
grade = 'C';
break;
default:
grade = 'D';
break;
}
printf("Grade is: %c\n", grade); // 输出: Grade is: C
return 0;
}
执行流程:
score是85,score / 10的结果是8。switch开始匹配。case 10和case 9不匹配。case 8匹配。- 程序执行
case 8中的代码:grade = 'B';。 - 没有遇到
break,所以程序会继续向下执行case 7的代码。 - 执行
case 7中的代码:grade = 'C';。grade的值被覆盖为'C'。 - 遇到
break;,switch语句结束。 - 打印结果
Grade is: C。
利用“贯穿”的场景:
上面的例子也展示了如何利用“贯穿”来简化代码。case 10 和 case 9 都需要执行 grade = 'A';,我们可以这样写:
case 10:
case 9:
grade = 'A';
break;
当匹配到 10 或 9 时,都会执行 grade = 'A'; 然后跳出。
示例 3:使用 default
当输入值不在预期范围内时,default 分支会处理它。

#include <stdio.h>
int main() {
int option;
printf("Enter an option (1-3): ");
scanf("%d", &option);
switch (option) {
case 1:
printf("You selected Option 1.\n");
break;
case 2:
printf("You selected Option 2.\n");
break;
case 3:
printf("You selected Option 3.\n");
break;
default:
printf("Invalid option. Please choose between 1 and 3.\n");
break;
}
return 0;
}
switch-case vs if-else if-else
| 特性 | switch-case |
if-else if-else |
|---|---|---|
| 判断条件 | 只能判断相等 () | 可以判断任何关系(, , >, <, >=, <=) |
| 数据类型 | 仅限整型 和 枚举型 | 任何数据类型(int, float, char, string 等) |
| 可读性 | 当判断多个离散的整数值时,结构更清晰 | 当判断条件复杂或范围时,更灵活、更清晰 |
| 性能 | 对于多分支情况,编译器有时可以生成更高效的跳转表(jump table)代码 | 性能通常也很好,但对于大量分支,可能不如 switch 高效 |
选择建议:
- 如果你要根据一个变量的多个离散整数值来执行不同的操作,并且这些值是固定的,优先使用
switch-case,代码结构更清晰。 - 如果你的判断条件涉及范围(如
x > 10 && x < 20)、不等(x != 0)或者涉及浮点数、字符串等,则必须使用if-else if-else。
最佳实践和注意事项
-
总是加上
break:除非你明确地想要利用“贯穿”特性,否则在每个case的末尾都应该加上break,这可以避免很多难以发现的逻辑错误。 -
为
default分支添加注释:即使你觉得所有情况都被case覆盖了,也最好加上一个空的default分支(default: break;)并附上注释,说明为什么没有处理它,这表明你考虑到了所有可能性,并且是有意为之的。 -
保持
default在最后:虽然default可以放在任何位置,但把它放在最后最符合人们的阅读习惯。 -
注意变量作用域:在 C99 标准及以后,你可以在
switch语句内部定义变量,但要特别注意变量的作用域,变量定义的语句会开始一个新的作用域块。switch (x) { case 1: int y = 10; // y 的作用域从这里开始 printf("%d\n", y); break; case 2: // printf("%d\n", y); // 错误!y 在这里不可见 break; }
switch-case 是 C 语言中一个非常强大且常用的控制流工具,理解其工作原理,特别是 break 语句和“贯穿”现象,是写出正确、健壮代码的关键,当你需要处理一个变量在多个固定整数值之间的多路选择时,switch-case 往往是比冗长的 if-else if-else 链更优雅、更清晰的选择。
