switch-case 是一种多路分支语句,它可以根据一个变量的值,从多个执行分支中选择一个来执行,它相当于 if-else if-else 链条的一种更清晰、更高效的替代方案(在特定情况下)。

(图片来源网络,侵删)
基本语法
switch-case 语句的基本结构如下:
switch (expression) {
case constant_expression1:
// 当 expression 的值等于 constant_expression1 时,执行的代码
break; // 可选,但强烈推荐
case constant_expression2:
// 当 expression 的值等于 constant_expression2 时,执行的代码
break; // 可选,但强烈推荐
case constant_expression3:
// 当 expression 的值等于 constant_expression3 时,执行的代码
break; // 可选,但强烈推荐
default:
// 当 expression 的值不匹配任何一个 case 时,执行的代码
break; // 可选,但强烈推荐
}
语法详解
a. switch (expression)
expression是一个整型表达式(包括int,char,short,long等,因为char在本质上是小整数)。- 它不能是浮点型(
float,double)或字符串类型。 switch会计算这个表达式的值,然后与下面每个case的值进行比较。
b. case constant_expression:
constant_expression必须是一个常量或常量表达式(10, 'A',2*5),不能是变量。- 每个
case的值必须是唯一的,不能有两个case标签使用相同的常量值。 - 当
switch的表达式的值与某个case的值匹配时,程序会从该case标签之后的语句开始执行,并依次向下执行,直到遇到break语句或switch语句块的末尾。
c. break; 语句
break是switch-case中最关键也最容易出错的点。break的作用是立即终止switch语句的执行,程序流程会跳转到switch语句块后面的第一条语句。- 如果某个
case后面没有break,程序会“穿透”(fall through)到下一个case,继续执行其代码,即使它的case值并不匹配,这有时是故意的(用于多个 case 共享同一段代码),但更多时候是编程失误。
d. default:
default 是一个可选的“默认”分支。
switch 表达式的值不匹配任何一个 case 的值,那么程序就会执行 default 标签后面的代码。
default 可以放在 switch 块的任何位置(通常在最后),但从可读性角度,放在最后是最好的实践。
default 后面也可以使用 break,但这不是必需的,因为 default 是最后一个分支时,break 之后就是 switch 的结束。
示例代码
示例 1:标准用法(带 break)
这是最常见的用法,每个 case 都是独立的。
#include <stdio.h>
int main() {
int day = 3;
char dayName[20];
switch (day) {
case 1:
strcpy(dayName, "Monday");
break;
case 2:
strcpy(dayName, "Tuesday");
break;
case 3:
strcpy(dayName, "Wednesday");
break;
case 4:
strcpy(dayName, "Thursday");
break;
case 5:
strcpy(dayName, "Friday");
break;
case 6:
strcpy(dayName, "Saturday");
break;
case 7:
strcpy(dayName, "Sunday");
break;
default:
strcpy(dayName, "Invalid day");
break;
}
printf("Day %d is %s\n", day, dayName); // 输出: Day 3 is Wednesday
return 0;
}
执行流程:
day 的值是 3。
switch 开始匹配。
case 1, case 2 都不匹配。
case 3 匹配成功,程序开始执行 strcpy(dayName, "Wednesday");。
- 遇到
break;,switch 语句立即结束,程序跳转到 printf。
示例 2:“穿透”效应(不带 break)
我们希望多个 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("Sorry, you failed.\n");
break;
default:
printf("Invalid grade.\n");
break;
}
return 0;
}
执行流程:
grade 的值是 'B'。
switch 匹配到 case 'B'。
- 由于
case 'B' 后面没有 break,程序会继续向下执行,进入 case 'C' 的代码块。
- 执行
printf("Good job!\n");。
case 'C' 后面有 break,switch 语句结束。
示例 3:default 的位置
default 可以放在任何位置,但逻辑上通常放在最后。
#include <stdio.h>
int main() {
int number = 5;
switch (number) {
default:
printf("Number is not 1, 2, or 3.\n");
break; // 虽然是最后一个,但加上 break 是好习惯
case 1:
printf("Number is 1.\n");
break;
case 2:
printf("Number is 2.\n");
break;
case 3:
printf("Number is 3.\n");
break;
}
return 0;
}
执行流程:
number 的值是 5。
switch 从上到下查找匹配的 case。
case 1, case 2, case 3 都不匹配。
- 程序执行
default 分支,打印 Number is not 1, 2, or 3.。
switch-case vs. if-else if-else
特性
switch-case
if-else if-else
判断条件
只能判断整型或字符型常量
可以判断任何类型的表达式(浮点、字符串、逻辑等)
代码结构
对于多分支选择,结构更清晰,可读性高
对于少量分支或复杂条件,结构灵活
执行效率
通常效率更高,因为编译器可以生成跳转表,实现直接跳转,而不是像 if 那样逐一比较
效率相对较低,需要从上到下依次判断条件
break
需要 break 来防止“穿透”
每个分支都是独立的,不需要 break
共享逻辑
必须依赖“穿透”来实现,容易出错
可以用 &&, 等逻辑操作符轻松实现
选择建议:
(图片来源网络,侵删)
- 当你需要根据一个整型变量的值进行多路分支,并且分支较多(4 个以上)时,优先使用
switch-case,因为它更清晰。
- 当你的判断条件很复杂(
if (x > 10 && y < 5)),或者判断的类型不是整型(if (strcmp(str, "hello") == 0)),或者分支很少时,使用 if-else if-else。
注意事项和常见错误
-
忘记 break:这是最常见的错误,会导致逻辑混乱,程序执行了不该执行的代码。
// 错误示例
int x = 2;
switch (x) {
case 1:
printf("One\n");
case 2: // 匹配到这里
printf("Two\n"); // 执行
case 3: // 因为没有 break,继续执行
printf("Three\n"); // 也执行了!
default:
printf("Default\n"); // 也执行了!
}
// 输出:
// Two
// Three
// Default
-
switch 表达式不是整型:编译器会报错。
// 错误示例
double d = 1.2;
switch (d) { // 错误:switch 表达式不能是 double 类型
case 1.2:
// ...
}
-
case 值不是常量:编译器会报错。
// 错误示例
int a = 5;
int b = 10;
switch (a) {
case b: // 错误:case 标签必须是常量表达式
// ...
}
-
多个 case 使用相同的值:编译器会报错。
// 错误示例
switch (a) {
case 1:
// ...
case 1: // 错误:重复的 case 值
// ...
}
switch-case 是 C 语言中一个非常强大的控制流工具,特别适用于处理基于单一整型变量的多路选择问题,理解其核心机制——匹配和执行以及break 的重要性——是正确使用它的关键。break 是防止代码“穿透”的“安全阀”,而 default 则是处理所有“意外情况”的“兜底方案”。
default是一个可选的“默认”分支。switch表达式的值不匹配任何一个case的值,那么程序就会执行default标签后面的代码。default可以放在switch块的任何位置(通常在最后),但从可读性角度,放在最后是最好的实践。default后面也可以使用break,但这不是必需的,因为default是最后一个分支时,break之后就是switch的结束。
示例代码
示例 1:标准用法(带 break)
这是最常见的用法,每个 case 都是独立的。
#include <stdio.h>
int main() {
int day = 3;
char dayName[20];
switch (day) {
case 1:
strcpy(dayName, "Monday");
break;
case 2:
strcpy(dayName, "Tuesday");
break;
case 3:
strcpy(dayName, "Wednesday");
break;
case 4:
strcpy(dayName, "Thursday");
break;
case 5:
strcpy(dayName, "Friday");
break;
case 6:
strcpy(dayName, "Saturday");
break;
case 7:
strcpy(dayName, "Sunday");
break;
default:
strcpy(dayName, "Invalid day");
break;
}
printf("Day %d is %s\n", day, dayName); // 输出: Day 3 is Wednesday
return 0;
}
执行流程:
day的值是3。switch开始匹配。case 1,case 2都不匹配。case 3匹配成功,程序开始执行strcpy(dayName, "Wednesday");。- 遇到
break;,switch语句立即结束,程序跳转到printf。
示例 2:“穿透”效应(不带 break)
我们希望多个 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("Sorry, you failed.\n");
break;
default:
printf("Invalid grade.\n");
break;
}
return 0;
}
执行流程:
grade的值是'B'。switch匹配到case 'B'。- 由于
case 'B'后面没有break,程序会继续向下执行,进入case 'C'的代码块。 - 执行
printf("Good job!\n");。 case 'C'后面有break,switch语句结束。
示例 3:default 的位置
default 可以放在任何位置,但逻辑上通常放在最后。
#include <stdio.h>
int main() {
int number = 5;
switch (number) {
default:
printf("Number is not 1, 2, or 3.\n");
break; // 虽然是最后一个,但加上 break 是好习惯
case 1:
printf("Number is 1.\n");
break;
case 2:
printf("Number is 2.\n");
break;
case 3:
printf("Number is 3.\n");
break;
}
return 0;
}
执行流程:
number的值是5。switch从上到下查找匹配的case。case 1,case 2,case 3都不匹配。- 程序执行
default分支,打印Number is not 1, 2, or 3.。
switch-case vs. if-else if-else
| 特性 | switch-case |
if-else if-else |
|---|---|---|
| 判断条件 | 只能判断整型或字符型常量 | 可以判断任何类型的表达式(浮点、字符串、逻辑等) |
| 代码结构 | 对于多分支选择,结构更清晰,可读性高 | 对于少量分支或复杂条件,结构灵活 |
| 执行效率 | 通常效率更高,因为编译器可以生成跳转表,实现直接跳转,而不是像 if 那样逐一比较 |
效率相对较低,需要从上到下依次判断条件 |
break |
需要 break 来防止“穿透” |
每个分支都是独立的,不需要 break |
| 共享逻辑 | 必须依赖“穿透”来实现,容易出错 | 可以用 &&, 等逻辑操作符轻松实现 |
选择建议:

(图片来源网络,侵删)
- 当你需要根据一个整型变量的值进行多路分支,并且分支较多(4 个以上)时,优先使用
switch-case,因为它更清晰。 - 当你的判断条件很复杂(
if (x > 10 && y < 5)),或者判断的类型不是整型(if (strcmp(str, "hello") == 0)),或者分支很少时,使用if-else if-else。
注意事项和常见错误
-
忘记
break:这是最常见的错误,会导致逻辑混乱,程序执行了不该执行的代码。// 错误示例 int x = 2; switch (x) { case 1: printf("One\n"); case 2: // 匹配到这里 printf("Two\n"); // 执行 case 3: // 因为没有 break,继续执行 printf("Three\n"); // 也执行了! default: printf("Default\n"); // 也执行了! } // 输出: // Two // Three // Default -
switch表达式不是整型:编译器会报错。// 错误示例 double d = 1.2; switch (d) { // 错误:switch 表达式不能是 double 类型 case 1.2: // ... } -
case值不是常量:编译器会报错。// 错误示例 int a = 5; int b = 10; switch (a) { case b: // 错误:case 标签必须是常量表达式 // ... } -
多个
case使用相同的值:编译器会报错。// 错误示例 switch (a) { case 1: // ... case 1: // 错误:重复的 case 值 // ... }
switch-case 是 C 语言中一个非常强大的控制流工具,特别适用于处理基于单一整型变量的多路选择问题,理解其核心机制——匹配和执行以及break 的重要性——是正确使用它的关键。break 是防止代码“穿透”的“安全阀”,而 default 则是处理所有“意外情况”的“兜底方案”。
