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
}
}