C/C++中switch語句為什麼匹配到標籤後不跳出?

C/C++ switch case語句中,匹配到case後需要在其後代碼塊里添加break語句,否則將依次執行後面的部分,這是歷史原因還是因為這麼做確實有其道理?


@vczh大大的答案展現了C的switch語句的默認fallthrough特性的應用。

送上傳送門:Duff"s device


C語言他爹:switch和case就是goto和label,你們不要想太多。

既然是goto,那自然就可以穿插在一些別的語句里,譬如說這樣(給你們開開眼界),下面的代碼執行Fuck多達i次,然後i == 0:

switch(i % 8)
{
while(i &> 0)
{
case 0: Fuck(); i--;
case 7: Fuck(); i--;
case 6: Fuck(); i--;
case 5: Fuck(); i--;
case 4: Fuck(); i--;
case 3: Fuck(); i--;
case 2: Fuck(); i--;
case 1: Fuck(); i--;
}
}


很多人認為這是C語言當初設計時的重大失誤之一

C語言的設計者認為,將break的任務交給程序員,能允許下面這種情況的編程,使語言更靈活

switch(val)
{
case 1:
case 2:
case 5:
case 8:
case 1000:
do_something();
break;
case XXX:
do_other_thing();
break;
......
}

如果每個case自動跳出,則會變得很麻煩。

C語言出現後,對於各種C代碼的統計表明,即便是在編譯器代碼這種理論上需要較多使用上述特性的地方,實際出現的次數也十分有限。(印象是6%還是多少,記不清了待我查查)

這樣設計switch所帶來的靈活遠遠不及自動跳出所帶來的便捷——要知道很多著名的bug就是因為忘了一行 break所導致的。

由於C語言的深遠影響力,此後的類C語言(C++ Java ObjC )迫不得已繼承了這種語法規定。由於在實際工作中上述特性的正當使用情況極為稀少(大部分是忘掉了break而已),故很多代碼規範要求使用上述特性時必須特別加註釋說明,有些IDE也會對於不加break的情況提示warning,暗示了這一特性的失敗。

C#的設計似乎更加深思熟慮。一方面,對於空case語句仍然允許上述特性;另一方面,一旦case內出現了實際語句,則必須使用break或等價的跳出語法,否則報error

以上評論不是我的觀點,記不清是出自哪本書了,是《C++沉思錄》還是《C專家編程》。。。望見過的告訴我一聲


那是因為C需要照顧那些已經習慣goto的人來使用fallthrough執行一些非常特殊技巧的switch語句,所以普通人你們也給我老老實實寫break跳出吧!

你看Swift不就把這兩者和平地聯繫到了一起嗎?

var a = 0
switch a{
case 0,1:
println(0)
fallthrough
case 2:
println(2)
case 3:
println(3)
fallthrough
default:println("default")
}
//a == 0 || a == 1 =&> 0 2
//a == 2 =&> 2
//a == 3 =&> 3 default

多麼方便(逃)


因為c代碼要翻譯成彙編,再機器代碼。

在switch翻譯的過程中 case 是順序執行的。

與之對比的就是 if-else,他有一個判斷和跳轉的過程。


需要break國標就是這麼定的


推薦閱讀:

怎麼理解 P 問題和 NP 問題?
FAQ-開發時需要先完成全部詳細設計/類圖嗎,如果需要那要詳細到什麼程度?
從接觸編程到工作,你們對編程的認識是一個怎樣的變化過程?
為什麼C語言的Hello,world都是用printf輸出而不是puts?
C#與VC++在桌面軟體的開發比較?

TAG:編程語言 | 編程 | C編程語言 | C |