case 标签本身只是一个“路标”,它告诉 switch 语句:“当表达式的值等于这个 case 后面的常量时,就从这里开始执行。” 它不会自动停止程序的执行。

(图片来源网络,侵删)
核心概念:case 的“穿透” (Fall-through)
这是理解 switch 语句最关键的一点,当一个 case 匹配后,程序会执行该 case 后面的所有语句,直到遇到以下两种情况之一才会停止:
break;语句switch语句的结束大括号
如果没有 break;,程序会“穿透”到下一个 case 继续执行,这被称为 “fall-through”。
使用 break; 来终止 case
这是最常见的用法,每个 case 的最后都加上 break;,确保匹配后只执行当前 case 的代码块,然后立即退出 switch 结构。
示例1:标准用法(带 break)
#include <stdio.h>
int main() {
int day = 3;
char dayName[20];
switch (day) {
case 1:
strcpy(dayName, "Monday");
break; // 当 day == 1 时,执行到这里就跳出 switch
case 2:
strcpy(dayName, "Tuesday");
break; // 当 day == 2 时,执行到这里就跳出 switch
case 3:
strcpy(dayName, "Wednesday");
break; // 当 day == 3 时,执行到这里就跳出 switch
default:
strcpy(dayName, "Unknown day");
break; // 处理所有其他情况,然后跳出 switch
}
printf("Day is: %s\n", dayName); // 输出: Day is: Wednesday
return 0;
}
执行流程:

(图片来源网络,侵删)
day的值是3。switch开始匹配。case 1和case 2不匹配,跳过。case 3匹配,执行strcpy(dayName, "Wednesday");。- 遇到
break;,立即退出switch语句。 - 执行
printf语句。
利用“穿透”特性(不带 break)
我们希望多个 case 执行相同的代码块,这时,我们可以故意省略 break; 来利用“穿透”特性。
示例2:利用穿透(不带 break)
假设我们要根据分数评定等级:90-100是A,80-89是B,70-79是C,60-69是D,60以下是F,我们可以把分数范围合并到 case 中。
#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;
case 6:
grade = 'D';
break;
default: // 0-5 的情况都会穿透到这里
grade = 'F';
break;
}
printf("Grade: %c\n", grade); // 输出: Grade: B
return 0;
}
执行流程:
score是85,score / 10的结果是8。switch匹配case 8。- 执行
grade = 'B';。 - 遇到
break;,退出switch。
score 是 95:
score / 10的结果是9。switch匹配case 9。- 执行
grade = 'A';。 - 遇到
break;,退出switch。
score 是 100:
score / 10的结果是10。switch匹配case 10。- 因为
case 10后面没有break;,程序会“穿透”到下一个case(即case 9)。 - 执行
grade = 'A';。 - 遇到
case 9后面的break;,退出switch。
default 分支
default 是一个特殊的 case,它不进行任何匹配。switch 表达式的值与所有 case 都不匹配,程序就会执行 default 后面的代码块。
default是可选的,但强烈推荐使用,它可以作为一种“安全网”,捕获所有未预料到的值。default可以放在switch语句的任何位置(开头、中间或结尾),但通常放在最后,这样逻辑最清晰。default后面也应该有break;,除非你明确希望它穿透到下一个case(这种情况非常罕见)。
示例3:default 的使用
#include <stdio.h>
int main() {
int choice = 5;
switch (choice) {
case 1:
printf("Option 1 selected.\n");
break;
case 2:
printf("Option 2 selected.\n");
break;
default: // choice 不是 1 或 2,会执行这里
printf("Invalid choice. Please try again.\n");
break;
}
return 0;
}
switch 语句的语法规则
在写 switch 时,必须遵守以下规则:
-
switch表达式类型:- 表达式的类型必须是 整型 或 枚举类型 (
int,char,short,long,enum等)。 - 不能是浮点数(
float,double)或字符串。
- 表达式的类型必须是 整型 或 枚举类型 (
-
case标签值:- 每个
case后面的值必须是常量或常量表达式(如10, 'A',2*5)。 - 不能是变量(如
int x = 5; case x:是错误的)。 - 所有
case的值必须是唯一的,不能有重复。
- 每个
-
变量声明:
- 在 C89/C90 标准(最老的标准)中,不能在
case标签之间声明变量(int x;)。 - 在 C99 及之后的标准中,允许在
case标签之间声明变量,但必须用 把声明和它的作用域包裹起来,否则会产生编译错误。
// C99 及以后标准下的正确写法 switch (day) { case 1: { int hours = 8; printf("Work hours: %d\n", hours); break; } case 2: { int hours = 8; printf("Work hours: %d\n", hours); break; } // ... } - 在 C89/C90 标准(最老的标准)中,不能在
总结与最佳实践
| 特性 | 说明 | 示例 |
|---|---|---|
break; |
默认且最常用的用法,在每个 case 的末尾使用,以防止代码“穿透”到下一个 case。 |
case 1: ...; break; |
| 穿透 (Fall-through) | 有意识的用法,当多个 case 需要执行相同代码时,省略 break;。 |
case 10: case 9: grade = 'A'; break; |
default |
强烈推荐使用,作为“默认”情况,处理所有未匹配的值,提高代码的健壮性。 | default: ...; break; |
switch vs if-else |
- 当有多个离散的、基于整型值的条件分支时,switch 更清晰、效率可能更高。- 当条件是范围判断(如 x > 10 && x < 20)、浮点数比较或复杂逻辑时,必须使用 if-else。 |
if (score > 90) ... else if (score > 80) ... |
核心要点:
case只是一个入口点,break;才是出口。 记住这句话,你就能掌握 C 语言switch语句的精髓。
