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 (expression)
expression是一个整型表达式(在 C99 标准之前,只允许是int类型,C99 及以后可以是int、char、enum或其他可以隐式转换为int的类型)。- 这个表达式的值会与每个
case后面的常量进行比较。
case constant:
constant必须是一个常量或常量表达式(不能是变量)。- 每个
case的值必须是唯一的,不能重复。 - 当
switch表达式的值与某个case的常量匹配时,程序就会从该case处开始执行代码。
break;
- 这是
switch语句中非常重要的部分! break语句的作用是立即跳出switch语句,防止程序继续执行下一个case的代码。- 如果没有
break,程序会继续执行下一个case的代码,这种现象称为“贯穿”(fall-through),这在某些情况下是有意为之的,但大多数情况下,忘记写break是一个常见的错误。
default:
default是可选的,但强烈推荐使用。switch表达式的值与任何一个case都不匹配,程序就会执行default分支中的代码。default分支通常放在switch语句的最后,但它也可以放在任何位置。
工作流程
- 计算
switch(expression)的值。 - 将计算得到的值与第一个
case的常量进行比较。 - 如果匹配,则从该
case处开始执行代码,直到遇到break或switch语句的末尾。 - 如果不匹配,则跳到下一个
case进行比较。 - 如果所有
case都不匹配,并且存在default分支,则执行default分支的代码。 - 如果没有
default分支且所有case都不匹配,则switch语句不执行任何操作。
示例代码
示例 1:基本用法(带 break)
这是一个最典型的用法,根据输入的数字(1-7)输出对应的星期几。
#include <stdio.h>
int main() {
int day = 3;
char* dayName;
switch (day) {
case 1:
dayName = "Monday";
break;
case 2:
dayName = "Tuesday";
break;
case 3:
dayName = "Wednesday";
break;
case 4:
dayName = "Thursday";
break;
case 5:
dayName = "Friday";
break;
case 6:
dayName = "Saturday";
break;
case 7:
dayName = "Sunday";
break;
default:
dayName = "Invalid day";
break;
}
printf("Day %d is %s\n", day, dayName); // 输出: Day 3 is Wednesday
return 0;
}
示例 2:贯穿(Fall-through)特性
有时,我们需要多个 case 执行相同的代码块,这时就可以利用“贯穿”特性。
#include <stdio.h>
int main() {
char grade = 'B';
switch (grade) {
case 'A':
printf("Excellent!\n");
break;
case 'B':
case 'C':
printf("Good job!\n"); // 当 grade 是 'B' 或 'C' 时,都会执行这句
break;
case 'D':
printf("You passed.\n");
break;
case 'F':
printf("You failed.\n");
break;
default:
printf("Invalid grade.\n");
break;
}
return 0;
}
// 输出: Good job!
示例 3:忘记 break 的错误示例
这个例子展示了忘记 break 会发生什么。

(图片来源网络,侵删)
#include <stdio.h>
int main() {
int number = 2;
switch (number) {
case 1:
printf("This is case 1.\n");
break; // number 是 1,到这里就停止了
case 2:
printf("This is case 2.\n");
// 故意忘记 break
case 3:
printf("This is case 3.\n");
break;
default:
printf("This is the default case.\n");
}
return 0;
}
输出结果:
This is case 2.
This is case 3.
原因分析:
number的值是 2,与case 2匹配。- 程序开始执行
case 2的代码,打印 "This is case 2."。 - 由于没有
break,程序没有跳出switch,而是继续向下执行case 3的代码,打印 "This is case 3."。 - 遇到
case 3的break后,才最终跳出switch语句。
switch vs. if-else if-else
| 特性 | switch 语句 |
if-else if-else 语句 |
|---|---|---|
| 判断条件 | 只能判断相等 () | 可以判断任何关系 (>, <, , 等) |
| 表达式类型 | 整型表达式 | 任何表达式(布尔、浮点等) |
| 执行效率 | 通常更高,因为它通常实现为“跳转表”(jump table),查找速度快。 | 效率相对较低,因为可能需要逐个条件判断。 |
| 代码可读性 | 当需要检查一个变量与多个常量是否相等时,switch 结构更清晰。 |
当逻辑复杂或需要范围判断时,if-else 更灵活、更易读。 |
选择建议:
- 如果你的逻辑是 "
x等于 1...,x等于 2...,x等于 3...",优先使用switch。 - 如果你的逻辑是 "
x大于 10...,否则如果x小于 0...",或者需要组合条件,必须使用if-else。
C 语言中的新特性 (C++ 和 C99)
在 C 语言中,switch 语句的限制比 C++ 要严格一些。

(图片来源网络,侵删)
C99 的变化:
C99 标准允许 switch 语句的 expression 和 case 标签使用 long 类型,以及更宽的整型。
C++ 的扩展:
C++ 对 switch 做了重要的扩展,使其更安全、更强大:
- 作用域:在 C++ 中,可以在
switch语句内部定义变量,但必须放在case标签之前。 - 类型:C++ 的
switch可以接受更多类型,包括std::string(通过重载operator==)和枚举。 - 贯穿提示:C17 标准引入了属性
[[fallthrough]],用于明确表示你希望代码“贯穿”,这是一种更安全、更清晰的写法,可以避免忘记break的警告。
C++ 示例 (作用域):
// C++ 代码
switch (day) {
int x; // 在 C 中,这里会报错,在 C++ 中,只要在所有 case 之前定义即可。
case 1:
// ...
break;
case 2:
// ...
break;
}
C17 示例 (显式贯穿):
// C17 代码
switch (value) {
case 1:
printf("One\n");
[[fallthrough]]; // 明确告诉编译器和阅读者:这里会贯穿
case 2:
printf("One or Two\n");
break;
}
switch是 C 语言中处理多路分支的有效工具,特别适合基于单个整型变量的值进行选择。break语句是switch的核心,用于防止代码“贯穿”,除非你确实需要这种行为。default分支是一个好习惯,用于处理所有未预料到的情况。- 根据逻辑的复杂性,在
switch和if-else if-else之间做出明智的选择。
