switch 和 if-else 相比, 由于使用了 Binary Tree 算法, 绝大部分情况下 switch 会快一点, 除非是 if-else 的第一个条件就为 true.
说实话 我也没有深入研究过这个问题的根源
只是在实际开发中 没有人会去用很多很多 else if 的
都是用 switch case 的 后者比较清晰 给人感觉就是一个脑子很清楚的人写出来的东西
至于效率的本质 就让大企鹅去操心吧
编译器编译 switch 与编译 if...else... 不同不管有多少 case, 都直接跳转, 不需逐个比较查询
昨天发现了一本叫做 CSAPP 的书, 终于找到了关于 switch 问题的解答
这是一段 C 代码:
- /* $begin switch-c */
- int switch_eg(int x) { int result = x;
- switch (x) {
- case 100:
- result *= 13;
- break;
- case 102:
- result += 10;
- /* Fall through */
- case 103:
- result += 11;
- break;
- case 104:
- case 106:
- result *= result;
- break;
- default:
- result = 0;
- }
- return result;
- }
- /* $end switch-c */
用 GCC 汇编出来的代码如下:
- .file "switch.c"
- .version "01.01"
- gcc2_compiled.:
- .text
- .align 4
- .globl switch_eg
- .type switch_eg,@function
- switch_eg:
- pushl %ebp
- movl %esp,%ebp
- movl 8(%ebp),%edx
- leal -100(%edx),%eax
- cmpl ,%eax
- ja .L9
- jmp *.L10(,%eax,4)
- .p2align 4,,7
- .section .rodata
- .align 4
- .align 4
- .L10:
- .long .L4
- .long .L9
- .long .L5
- .long .L6
- .long .L8
- .long .L9
- .long .L8
- .text
- .p2align 4,,7
- .L4:
- leal (%edx,%edx,2),%eax
- leal (%edx,%eax,4),%edx
- jmp .L3
- .p2align 4,,7
- .L5:
- addl ,%edx
- .L6:
- addl ,%edx
- jmp .L3
- .p2align 4,,7
- .L8:
- imull %edx,%edx
- jmp .L3
- .p2align 4,,7
- .L9:
- xorl %edx,%edx
- .L3:
- movl %edx,%eax
- movl %ebp,%esp
- popl %ebp
- ret
- .Lfe1:
- .size switch_eg,.Lfe1-switch_eg
- .ident "GCC: (GNU) 2.95.3 20010315 (release)"
在上面的汇编代码中我们可以很清楚的看到 switch 部分被分配了一个连续的查找表, switch case 中不连续的部分也被添加上了相应的条目, switch 表的大小不是根据 case 语句的多少, 而是 case 的最大值的最小值之间的间距在选择相应 的分支时, 会先有一个 cmp 子句, 如果大于查找表的最大值, 则跳转到 default 子句而其他所有的 case 语句的耗时都回事 O(1)
相比于 if-else 结构, switch 的效率绝对是要高很多的, 但是 switch 使用查找表的方式决定了 case 的条件必须是一个连续的常量而 if-else 则可以灵活的多
可以看到 if-else 只是单纯地一个接一个比较, 效率比较低
可以看出, switch 的效率一般比 if-else 高
switch 效率高, 从汇编代码可以看出来
switch 只计算一次值 然后都是 test , jmp,
if...else 是每个条件都要计算一遍的.
switch 的效率与分支数无关
当只有分支比较少的时候, if 效率比 switch 高 (因为 switch 有跳转表)
分支比较多, 那当然是 switch
来源: http://www.bubuko.com/infodetail-2503684.html