游戲中接受到的消息那叫一個多如牛毛啊,這就涉及到switch case接受還是if else接受的效率問題
有人說這是個小問題,哈哈 精益求精嗎
看到了一篇兩者效率比較的文章:
switch...case與if...else的根本區別在于,switch...case會生成一個跳轉表來指示實際的case分支的地址,而這個跳轉表的索引號與switch變量的值是相等的。從而,switch...case不用像if...else那樣遍歷條件分支直到命中條件,而只需訪問對應索引號的表項從而到達定位分支的目的。
具體地說,switch...case會生成一份大小(表項數)為最大case常量+1的跳表,程序首先判斷switch變量是否大于最大case常量,若大于,則跳到default分支處理;否則取得索引號為switch變量大小的跳表項的地址(即跳表的起始地址+表項大小*索引號),程序接著跳到此地址執行,到此完成了分支的跳轉。如下代碼(gcc編譯,不開優化):
int main()
{
int j = 0;
int i = 1;
switch (i)
{
case 1:
j = 11;
break;
case 2:
j = 22;
break;
case 3:
j = 33;
break;
case 4:
j = 44;
break;
case 10:
j = 10;
default:
j = 88;
break;
}
return 0;
}
這是編譯后的部分匯編碼:
.file "test.c"
.text
.globl main
.type main, @function
main:
leal 4(%esp), %ecx
andl $-16, %esp
pushl -4(%ecx)
pushl %ebp
movl %esp, %ebp
pushl %ecx
subl $16, %esp
movl $0, -8(%ebp)
movl $1, -12(%ebp)
cmpl $10, -12(%ebp)
ja .L2
movl -12(%ebp), %eax
sall $2, %eax
movl .L8(%eax), %eax
jmp *%eax
.section .rodata
.align 4
.align 4
.L8:
.long .L2
.long .L3
.long .L4
.long .L5
.long .L6
.long .L2
.long .L2
.long .L2
.long .L2
.long .L2
.long .L7
.text
.L3:
movl $11, -8(%ebp)
jmp .L9
.L4:
movl $22, -8(%ebp)
jmp .L9
.L5:
movl $33, -8(%ebp)
jmp .L9
.L6:
movl $44, -8(%ebp)
jmp .L9
.L7:
movl $10, -8(%ebp)
.L2:
movl $88, -8(%ebp)
.L9:
movl $0, %eax
addl $16, %esp
popl %ecx
popl %ebp
leal -4(%ecx), %esp
ret
可以打個比方,switch...case訪問條件分支的方式像數組一樣,是隨機訪問;而if...else是順序訪問。
他們各自的特點:
1、 總體上說,switch...case 效率要高于同樣條件下的if...else,特別是當條件分支較多時。
2、switch...case占用較多的代碼空間,因為它要生成跳表,特別是當case常量分布范圍很大但實際有效值又比較少的情況,switch...case的空間利用率將變得很低。例如上面的代碼,如果把case 10改成case 100,則會生成101個表項,而大部分表項是指向同一分支(default分支)。switch...case是在以空間換時間。
3、switch...case只能處理case為常量的情況,對非常量的情況是無能為力的。例如 if (a > 1 && a < 100),是無法使用switch...case來處理的。
***注意:如果把例子中的case分支減少一個,則生成的匯編碼與if...else差別不大,此時不會生成跳表項,可見對于分支較少的情況,編譯器會做特殊處理。
原文地址:http://blog.csdn.net/kevinyujm/archive/2009/02/18/3907964.aspx