具體地說,switch...case會生成一份大小(表項數)爲最大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 %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 .L6
.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.由上面的彙編代碼可知道,switch...case佔用較多的代碼空間,因爲它要生成跳錶,特別是當case常量分佈範圍很大但實際有效值又比較少的情況,switch...case的空間利用率將變得很低。
3.switch...case只能處理case爲常量的情況,對非常量的情況是無能爲力的。例如 if (a > 1 && a < 100),是無法使用switch...case來處理的。所以,switch只能是在常量選擇分支時比ifelse效率高,但是ifelse能應用於更多的場合,ifelse比較靈活。
switch和if-else相比,由於使用了Binary Tree算法,絕大部分情況下switch會快一點,除非是if-else的第一個條件就爲true.
在實際開發中 沒有人會去用很多很多else if的
都是用 switch case 的 後者比較清晰 給人感覺就是一個腦子很清楚的人寫出來的東西
編譯器編譯switch與編譯if...else...不同。不管有多少case,都直接跳轉,不需逐個比較查詢。