[转]C语言茶余饭后之if...else PK switch...case
本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/kevinyujm/archive/2009/02/18/3907964.aspx
在學校學C的那會兒,就已經知道switch...case的執行效率要相對if...else較高了(大體上講),因為從字面上和邏輯上看,switch...case是不用像if...else那樣做一系列比較判斷就可以直接定位到相應的條件分支的。不過也沒有深究過其中的原理。后來由于一偶然原因,就明白了其中的細節。今日碰巧看到一篇blog,是講作者對此問題的思考,我覺得作者的理解大體上都是對的,不過下面跟帖的人,有人鄙夷,有人諷刺,實在是影響網容網貌,對作者本人也是沒有起碼的尊重,無法建立起平等的溝通,實在是不河蟹呀~~~:)
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差別不大,此時不會生成跳表項,可見對于分支較少的情況,編譯器會做特殊處理。
?
總結
以上是生活随笔為你收集整理的[转]C语言茶余饭后之if...else PK switch...case的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: vim 记录阅读信息
- 下一篇: C核心技术手册(五)