switch与ifelse的效率问题
switch与if..else 的执⾏的效率问题
今天读⼀前辈的程序,发现其在串⼝中断⾥⾯为了分析协议的报⽂类型,在中断函数⾥⾯使⽤if..else语句。因为报⽂类型在现在看来只有两种,以后有可能还会增加,不确定。
本⼈以为这样⽤有些不妥,为什么不⽤switch语句呢?猜想是不是因为效率⽅⾯的考虑呢,毕竟我们应该尽量是中断的处理代码更加简洁,时间效率更⾼才好。
所以本⼈就查相关资料,资料显⽰switch语句反⽽⽐ifelse的执⾏效率要⾼。
下⾯来详细描述switch与ifelse的区别。
具体地说,ase会⽣成⼀份⼤⼩(表项数)为最⼤case常量+1的跳表,程序⾸先判断switch变量是否⼤于最⼤case 常量,若⼤于,则跳到default分⽀处理;否则取得索引号为switch变量⼤⼩的跳表
项的地址(即跳表的起始地址+表项⼤⼩*索引号),程序接着跳到此地址执⾏,到此完成了分⽀的跳转。
//
int main()
{
unsigned int i,j;
i=3;
switch (i)
{
case 0:
j=0;
break;
case 1:
j=1;
break;
case 2:
j=2;
break;
case 3:
j=3;
break;
case 4:
j=4;
break;
default:
j=10;
break;
}
}
⽤gcc编译器,⽣成汇编代码(不开编译器优化)
.file "shiyan.c"
.text
.globl main
.type main, @function
main:
leal 4(%esp), %ecx
andl $-16, %esp
pushl -4(%ecx)
pushl -4(%ecx)
pushl %ebp
movl %esp, %ebp
pushl %ecx
subl $20, %esp
movl $3, -8(%ebp)
cmpl $4, -8(%ebp)
ja .L2
movl -8(%ebp), %eax
sall $2, %eax
movl .L8(%eax), %eax
jmp *%eax
.section .rodata
.align 4
.align 4
.L8:
.long .L3
.long .L4
.
long .L5
.long .L6switch case判断字符串
.long .L7
.text
.L3:
movl $0, -12(%ebp)
jmp .L11
.L4:
movl $1, -12(%ebp)
jmp .L11
.L5:
movl $2, -12(%ebp)
jmp .L11
.L6:
movl $3, -12(%ebp)
jmp .L11
.L7:
movl $4, -12(%ebp)
jmp .L11
.L2:
movl $10, -12(%ebp)
.L11:
addl $20, %esp
popl %ecx
popl %ebp
leal -4(%ecx), %esp
ret
.size main, .-main
.ident "GCC: (Ubuntu 4.3.3-5ubuntu4) 4.3.3" .section .note.GNU-stack,"",@progbits
由此看来,switch有点以空间换时间的意思,⽽事实上也的确如此。
1.当分⽀较多时,当时⽤switch的效率是很⾼的。因为switch是随机访问的,就是确定了选择值之后直接跳转到那个特定的分⽀,但是if。。else是遍历所以得可能值,知道到符合条件的分⽀。如此看来,switch的效率确实⽐ifelse要⾼的多。
2.由上⾯的汇编代码可知道,ase占⽤较多的代码空间,因为它要⽣成跳表,特别是当case常
量分布范围很⼤但实际有效值⼜⽐较少的情况,ase的空间利⽤率将变得很低。
ase只能处理case为常量的情况,对⾮常量的情况是⽆能为⼒的。例如 if (a > 1 && a < 100),是⽆法使⽤ase来处理的。所以,switch只能是在常量选择分⽀时⽐ifelse效率⾼,但是ifelse能应⽤于更多的场合,ifelse⽐较灵活。
由此看来,上⾯前辈的中断处理程序中⽤switch是⽐较合适的,即节省了时间,⽽且对于以后程序的扩展也是很⽅便。因为报⽂类型这个值基本上都是⽤整形常量来表⽰的。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论