switch...case和if...else效率比較

1、switch…case結構的彙編表示

寫入switch…case結構的代碼:

int fun(char c)
{
   char res;
   switch(c)
   {
   case 'a':
       res='a';
       break;
   case 'e':
      res='e';
      break;
  case 'i':
      res='i';
      break;
  case 'o':
      res='o';
      break;
  case 'u':
      res='u';
      break;
  default:
      res=' ';
  }
}

用gcc產生的彙編代碼是:

00000000 <fun>:
   0:   55                      push   %ebp
   1:   89 e5                   mov    %esp,%ebp
   3:   83 ec 14                sub    $0x14,%esp
   6:   8b 45 08                mov    0x8(%ebp),%eax
   9:   88 45 ec                mov    %al,-0x14(%ebp)
   c:   0f be 45 ec             movsbl -0x14(%ebp),%eax
  10:   83 e8 61                sub    $0x61,%eax
  13:   83 f8 14                cmp    $0x14,%eax
  16:   77 27                   ja     3f <fun+0x3f>
  18:   8b 04 85 00 00 00 00    mov    0x0(,%eax,4),%eax
  1f:   ff e0                   jmp    *%eax
  21:   c6 45 ff 61             movb   $0x61,-0x1(%ebp)
  25:   eb 1c                   jmp    43 <fun+0x43>
  27:   c6 45 ff 65             movb   $0x65,-0x1(%ebp)
  2b:   eb 16                   jmp    43 <fun+0x43>
  2d:   c6 45 ff 69             movb   $0x69,-0x1(%ebp)
  31:   eb 10                   jmp    43 <fun+0x43>
  33:   c6 45 ff 6f             movb   $0x6f,-0x1(%ebp)
  37:   eb 0a                   jmp    43 <fun+0x43>
  39:   c6 45 ff 75             movb   $0x75,-0x1(%ebp)
  3d:   eb 04                   jmp    43 <fun+0x43>
  3f:   c6 45 ff 20             movb   $0x20,-0x1(%ebp)
  43:   0f be 45 ff             movsbl -0x1(%ebp),%eax
  47:   c9                      leave  
  48:   c3                      ret  

計算機中處理switch…case結構時,會生成跳轉表,根據變量的取值跳轉到合適的分支。在上面的例子中,變量c存放在ebp偏移8字節的位置,它首先減去97,如果大於20則跳轉到默認分支。在執行完對應的分支後,每個分支後都有jmp43語句用於跳轉到函數的結尾。

2.if…else語句的彙編表示

上面的代碼寫成if…else的形式,產生的彙編代碼是:

00000000 <fun>:
   0:   55                      push   %ebp
   1:   89 e5                   mov    %esp,%ebp
   3:   83 ec 14                sub    $0x14,%esp
   6:   8b 45 08                mov    0x8(%ebp),%eax
   9:   88 45 ec                mov    %al,-0x14(%ebp)
   c:   80 7d ec 61             cmpb   $0x61,-0x14(%ebp)
  10:   75 06                   jne    18 <fun+0x18>
  12:   c6 45 ff 61             movb   $0x61,-0x1(%ebp)
  16:   eb 34                   jmp    4c <fun+0x4c>
  18:   80 7d ec 65             cmpb   $0x65,-0x14(%ebp)
  1c:   75 06                   jne    24 <fun+0x24>
  1e:   c6 45 ff 65             movb   $0x65,-0x1(%ebp)
  22:   eb 28                   jmp    4c <fun+0x4c>
  24:   80 7d ec 69             cmpb   $0x69,-0x14(%ebp)
  28:   75 06                   jne    30 <fun+0x30>
  2a:   c6 45 ff 69             movb   $0x69,-0x1(%ebp)
  2e:   eb 1c                   jmp    4c <fun+0x4c>
  30:   80 7d ec 6f             cmpb   $0x6f,-0x14(%ebp)
  34:   75 06                   jne    3c <fun+0x3c>
  36:   c6 45 ff 6f             movb   $0x6f,-0x1(%ebp)
  3a:   eb 10                   jmp    4c <fun+0x4c>
  3c:   80 7d ec 75             cmpb   $0x75,-0x14(%ebp)
  40:   75 06                   jne    48 <fun+0x48>
  42:   c6 45 ff 75             movb   $0x75,-0x1(%ebp)
  46:   eb 04                   jmp    4c <fun+0x4c>
  48:   c6 45 ff 20             movb   $0x20,-0x1(%ebp)
  4c:   0f be 45 ff             movsbl -0x1(%ebp),%eax
  50:   c9                      leave  
  51:   c3                      ret    

可見,如果輸入了字符a,這個程序將不需要跳轉,這時if…else的效率要高於switch…case.如果是輸入了字符o或者u,程序將多次跳轉,程序的分支變多時,必然會導致效率降低。

3.switch…case語句和if…else效率比較

這裏不考慮編譯器的優化和條件傳送(條件傳送介紹),僅僅從跳轉次數來比較兩者的效率。

switch…case結構中有跳轉表,輸入的字符只要經過一次比較就可以正確的找到跳轉分支,所以平均情況下跳轉次數爲1.

if…else結構如果有n個分支,分別記爲n0,n1,n2,n3,…n(i-1),每個分支出現的概率假設未pi,分別爲p0,p1,p2,p3,…p(i-1)。執行第一分支前不需要跳轉,其它分支均需要跳轉,執行第二個分支之前需要跳轉一次,第三個分支需要跳轉兩次…需要跳轉平均跳轉的次數s爲:
這裏寫圖片描述
如果
這裏寫圖片描述>1
,則此時if…case的效率是小於switch…case的,如果它的值小於1,此時if…else的效率高於switch…case。

假設if…else分支的每個分支出現的概率相同,即1/n,上面的跳轉次數的期望值可以改寫爲:
這裏寫圖片描述

如果n=3,則期望的跳轉次數爲1,剛好與switch…case相同。由此,如果選擇分支大於3的時候,選用switch…case結構效率會更高一些,而小於3時,選用if…else結構更好。

總結:在選擇分支較多時,選用switch…case結構會提高程序的效率,但switch不足的地方在於只能處理字符或者數字類型的變量,if…else結構更加靈活一些,if…else結構可以用於判斷表達式是否成立,比如if(a+b>c),if…else的應用範圍更廣,switch…case結構在某些情況下可以替代if…else結構。

轉載自http://www.2cto.com/os/201404/291376.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章