switch() 语句
当你希望程序根据特定测试变量的值执行许多不同的操作时,switch
语句非常有用。
switch
语句的示例用法如下:
int a = 1;
switch (a) {
case 1:
puts("a is 1");
break;
case 2:
puts("a is 2");
break;
default:
puts("a is neither 1 nor 2");
break;
}
这个例子相当于
int a = 1;
if (a == 1) {
puts("a is 1");
} else if (a == 2) {
puts("a is 2");
} else {
puts("a is neither 1 nor 2");
}
如果使用 switch
语句时 a
的值为 1,则将打印 a is 1
。如果 a
的值是 2,那么将打印 a is 2
。否则,将打印 a is neither 1 nor 2
。
case n:
用于描述当传递给 switch
语句的值为 n 时执行流将跳入的位置。 n 必须是编译时常量,并且在一个 switch
语句中最多只能存在一次 n 。
default:
用于描述当值与 case n:
的任何选项都不匹配时。在每个 switch 语句中包含 default
案例以捕获意外行为是一种好习惯。
跳出 switch
区块需要一个 break;
声明。
注意: 如果你不小心忘记在 case
结束后添加 break
,编译器将假定你打算 通过 并且将执行所有后续的 case 语句(如果有的话)(除非在中找到 break 语句)任何后续案例),无论后续 case 语句是否匹配。此特定属性用于实现 Duff 的设备 。这种行为通常被认为是 C 语言规范中的一个缺陷。
下面是一个显示没有 break;
的影响的例子:
int a = 1;
switch (a) {
case 1:
case 2:
puts("a is 1 or 2");
case 3:
puts("a is 1, 2 or 3");
break;
default:
puts("a is neither 1, 2 nor 3");
break;
}
当 a
的值为 1 或 2 时,将打印 a is 1 or 2
和 a is 1, 2 or 3
。当 a
为 3 时,仅打印 a is 1, 2 or 3
。否则,将打印 a is neither 1, 2 nor 3
。
请注意,default
的情况不是必需的,尤其是当你在 switch
中获得的值集完成并在编译时已知时。
最好的例子是在 enum
上使用 switch
。
enum msg_type { ACK, PING, ERROR };
void f(enum msg_type t)
{
switch (t) {
case ACK:
// do nothing
break;
case PING:
// do something
break;
case ERROR:
// do something else
break;
}
}
这样做有很多好处:
- 如果你没有处理一个值,大多数编译器都会报告一个警告(如果存在
default
案例则不会报告) - 出于同样的原因,如果你向
enum
添加一个新值,你会收到你忘记处理新值的所有地方的通知(使用default
的情况,你需要手动探索你的代码搜索这样的情况) - 读者不需要弄清楚“
default:
隐藏了什么”,是否有其他的enum
值或者它是否是以防万一的保护。如果还有其他的enum
值,那么编码器是否有意为他们使用了default
的情况,还是在添加值时引入了一个错误? - 处理每个
enum
值使代码自我解释,因为你不能隐藏在外卡后面,你必须明确地处理它们中的每一个。
然而,你不能阻止别人写下如下的邪恶代码:
enum msg_type t = (enum msg_type)666; // I'm evil
因此,如果你确实需要,可以在切换之前添加额外的检查以检测它。
void f(enum msg_type t)
{
if (!is_msg_type_valid(t)) {
// Handle this unlikely error
}
switch(t) {
// Same code than before
}
}