既生if/else,何生switch/case?

來源:互聯網
上載者:User

在我第一篇筆記 《C++ 的 “武”和“功”》中,我順口提到switch/case的存在和“浮點數”有點淵源(或者說,有點瓜葛),有網友問了這一點。因為它本是我的書《白話C++》中的一小段,我砍點,添點,結果不長不短的,乾脆就寫成第二篇吧。

 

要讀懂這篇文章,前提條件是知道“floating_point@computer/浮點數在電腦”並不那麼精確;第二,會“二分尋找法”。而要正確回答課後的問題,最好還得複習一下“範圍”。

 

類似這樣的代碼:

Code:
  1. if ( i == 1)  
  2. {}  
  3. else if (i == 2)  
  4. {}  
  5. else if (i == 5)  
  6. {}  
  7. else if (i == 8)  
  8. {}  
  9. else if (i == 9)  
  10. {}  

您當過“人肉編譯器”嗎?如果我是一個編譯器,那麼我會為上面的代碼產生最佳化,如何最佳化?我會首先讓i和5相減(組合語言就愛這麼比較),減完結果,無非是 等於0,小於0 ,或 大於0。從而得出是停止比較(0),還是往前找(<0),或往後找(>0)——我知道你已經非常鄙視我了:這不就是大一時的“二分尋找法”嘛(非扯出個人肉編譯器)!


人肉編譯器比較“牛”的地方是,“掃一眼”,就放心地發現,這是一位有良心的同學寫出來的代碼,因為:拿來比較的目標數(1、2、5……),有意地從小排到大了,滿足二分尋找法對資料數列必須“有序”的條件。但要讓真實編譯器來處理,想確保這個最佳化條件成立,也不難,只要滿足那麼幾個條件,其中一個和浮點數有關:

首先,別把整數及其相容類型以外的資料類型,拿來說事! 比如,你拿個不可能直接用CMP指令完成比較的“浮點數”來比較,那編譯器絕不上當,那樣產生的最佳化結果,可能是錯誤。

還有很多條件,且多說一個: 每個if 中的條件,必須是無副作用的,下面的語句,怎麼也不能跳著來比較吧:

Code:
  1. if (foo() == 1)  
  2. {}  
  3. else if (foo() == 2)  
  4. {}  
  5. else if (foo() == 4)  
  6. {}  
  7. else if (foo() == 8)  
  8. {}  
  9. //...  

foo()最終被執行幾遍,這和if條件被判斷了幾次有關,這是正確性問題。還想按中值預測一下它,搞點二分法來做速度最佳化在這裡太不靠譜了。


如此種種,if 能保證嗎? 不能,你看,if 什麼都能比,浮點數,整數,字串……所以,C語言的作者造了一個受限版的if/elseif, 那就是:switch/case; switch/case 存在和浮點數(曾經是令電腦先賢們最為頭痛的問題之一)沒有關係嗎?有,它就是為了躲開浮點數比較才創造出來的,否則都有全能的if/else 比較了,還搞個怪怪的switch/case做什嗎?

 

你問我,人家有些語言中的swith/case,也能比較浮點數,甚至還可以拿來比較字串呢……那是因為,這些語言要麼不是效率為第一設計目標,要麼,它們雖然也講究運行效率,但它們是C/C++的晚輩,當初又希望從C++程式員抓點人遷移成它們的第一批使用者,所以它們在文法上“留”住switch/case,但去掉了那些限制(反正它們又不直接編譯成機器語言)。

 

如果不瞭解這一點,就會有一些學生,向我抱怨啊:老師,K&R好怪哪,幹嘛就非不讓switch拿來判斷一個浮點數呢?難道編譯器要做到一點很困難嗎?當然不難,但為了效率,所以以下代碼,任何一個靠譜的C/C++編譯器,都不會放過它:
 

Code:
  1. //錯誤的C++代碼:  
  2. double d = 0.0;  
  3. switch(d)  
  4. {  
  5.   case 1 :  
  6.      //...  
  7.      break;  
  8.   case 1.5 :  
  9.     //...  
  10. }  

我出門上班時,本就一條路可走,但因為我知道在這條光明的大道上,可能會有一位債主癡癡地等我,嚴重影響我上班的效率。所以我決定披荊斬棘,再走出一條小路出來……後來時光荏苒,那位債主已經放棄它的需求,但路已經成了路,上面走著許許多多不知情的人們……

=============================================================

課後:對了你能理解為什麼下面的switch/case代碼,也是錯誤的嗎?

(經各位指出,下面兩段代碼有誤,並且位置正好相反,為了讓後來者知道在後面開貼討論什麼,就不刪除了,直接把糾正過的附後吧。)

Code:
  1. int i;    
  2.    
  3. //...    
  4.   
  5. //錯誤的代碼:  
  6. switch(i)    
  7. {    
  8.    case 1 :    
  9.       int b;    
  10.       cin >> b;    
  11.       break;    
  12.    case 2 :    
  13.      cout << i;    
  14.       break;    
  15.      //...    
  16.  }    

而下面這樣一改,就合法了:

Code:
  1. int i;    
  2.    
  3. //...    
  4.   
  5. //合法的代碼:  
  6. switch(i)    
  7. {    
  8.    case 1 :    
  9.    {   int b;    
  10.        cin >> b;    
  11.        break;    
  12.    }  
  13.    case 2 :    
  14.       cout << i;    
  15.       break;    
  16.      //...    
  17.  }   

=============================

附後:

真正錯誤的:

Code:
  1. int i;    
  2.    
  3. //...    
  4.   
  5. //錯誤的代碼:  
  6. switch(i)    
  7. {    
  8.    case 1 :    
  9.    {   int b;    
  10.        cin >> b;    
  11.        break;    
  12.    }  
  13.    case 2 :    
  14.       cout << b;    
  15.       break;    
  16.      //...    
  17.  }   

正確的:

Code:
  1. int i;    
  2.    
  3. //...    
  4.   
  5. //合法的代碼:  
  6. switch(i)    
  7. {    
  8.    case 1 :    
  9.       int b;    
  10.        cin >> b;    
  11.        break;    
  12.      
  13.    case 2 :    
  14.       cout << b; //沒有初始化   
  15.       break;    
  16.      //...    
  17.  }   

-------------------------------------

如果您想與我交流,請點擊如下連結成為我的好友:
http://student.csdn.net/invite.php?u=112600&c=f635b3cf130f350c 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.