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

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