switch為C提供的條件判斷式,只能用來比較數值或字元。ANSI C標準規定switch裡面的case至少需支援257個成員,因為字元長度為8-bit (256個可用字元 + EOF)
貫穿 (Fall Through)
貫穿(Fall Through)指的是當switch進到特定的case中執行完動作後並不會自動break,執行流程會繼續往下跑直到看到break聲明。某些場合我們會使用貫穿的特性讓程式較精簡,但使用此特性的場合並不多,因此仍然必須仔細確認程式流程
1 | switch (2) { |
此段程式碼結果如下,由case2貫穿到default
Break
Break除了使用在switch來跳出外,也可用在迴圈中的跳出,也因此可能造成非預期的流程但編譯器無法檢查出來
此段程式在if (y == OTHER_STUFF)
後接了break(顯然是coding上有錯誤),原本是預期break之後可以執行initialize_modes_pointer();
但因為此break在case2裡,且也不在迴圈裡面,因此會直接跳離此switch判斷式造成非預期的行為
1 | switch (2) { |
Default
當所有的case都不滿足時會進入default條件裡面(如果有的話),通常我們習慣將default放在最後一個判斷,但其實default是可以放在任何位置的
1 | switch (4) { |
此段程式,然仍能夠正確的達到預期的結果
這時衍伸出一個有趣的問題,如果說default可放在任意位置,那是否代表switch在CPU執行時的行為和if…else並不相同,而是比較接近於goto的使用呢?
我們在x86的機器上將以上的程式碼編譯成組合語言
mov DWORD PTR tv64[ebp], 4
將數字4移到ebp
cmp DWORD PTR tv64[ebp], 1
將數字1和ebp比較
je SHORT $LN4@main
若相等則跳到LN4
因為ebp皆不等於1,2,3因此最終會跳到LN3,另外default裡沒有break,從組合語言可以看到最終沒有接jmp,因此會繼續往下跑執行case2最終執行jmp到LN5
由此可見switch是由建立多個label+jmp到特地位置,而if…else則是經過不斷的cmp+jmp,兩者並不相同