2020-11-27(switch的优化问题)
第一次看switch的case表的時候,那是半年前了,看完了有序線性然后去看非線性索引時,實在看不下去了,今天再一次拿出這本書,把switch 的 有序線性 ,非線性,以及 判斷樹 看了一遍,感觸挺深的吧,接下來讓我們一起被switch虐吧。
1.首先,二話不說,上代碼,代碼具有較高說服力
兩份代碼debug版本相比較后,大家可以發現,if……else if 結構會在條件跳轉后緊跟語句塊;而switch結構則將所有條件跳轉都放置到了一起,并沒有發現case語句的蹤影。通過條件跳轉指令,跳轉到相應的case語句塊中,因此每個case的執行是由switch比較結果引導“跳”過來的。所有的case語句塊都是連在一起的,這樣是為了實現C語法的需要,在case 語句塊中沒有break語句時,可以順序執行后續的case語句塊。
當switch的分支小于4的情況下,采用模擬if……else if 的方法,并沒有發揮出switch的優勢。當分支數大于3時,并且case的判定值存在明顯線性關系組合時,switch的優化特性便可以凸顯出來。
1.分支數大于3時,并且case的判定值存在明顯線性關系組合時:
會為case語句制作一份case地址數組(或者稱為“case地址表”),我一般叫它case表。
此數組保存了每個case語句塊的首地址,并且數組下標是以0為起始。
而case中的最小值是1,與case地址表的起始下標是不對應的,所以需要edx-1調整,使其可以作為表格的下標進行尋址。
如果沒有case對應的數值,編譯器以switch的結束地址或者default語句塊的首地址填充對應的表格
(舉個例子,也就是switch選項有 1,3,5,7,則case表(數組)里面第0,2,4,6項分別對應1,3,5,7,的地址,case表(數組)的1,3,5項全是switch的結束地址或者default語句塊的首地址)
這里也就是后面所說的 有序線性地址表重復保存switch的結束地址
case表項數:
case最大值-case最小值 ,中間空的直接用switch的結束地址或者default語句塊的首地址去填充。
2.難以構成跳轉表的switch
前提條件:索引表中保存了地址表中的下標值,索引表中最多可以存儲256項,每一項的大小為1字節,這決定了case值不可以超過1字節的最大表示范圍(0~255),因此索引表也只能存儲256項索引編號。
非線性的switch結構,可以采用制作索引表的方法來進行優化。索引表優化,需要兩張表:一張為case語句塊地址表(有多少個case,地址表就會有多少項),另一張為case語句塊索引表(索引表保存了地址表的下標值,它的大小等于最大case值和最小case值的差)
與上面制作單一的case線性地址表相比,制作索引表的方式更加節省空間,但是由于在執行時需要用過索引表來查詢地址表,會多出一次查詢地址表的過程,因此效率會有所下降。
此方案所占用的內存空間如下:
(MAX-MIN)1字節=索引表大小
SUM4字節=地址表大小
占用總字節數=((MAX-MIN)1字節)+(SUM4字節)
首先case值與索引表下標對齊操作:
case的最小值MIN對應是索引表(數組)的第0項,其它的(i)依次減去最小值對應索引表(數組)的第(i-MIN)項,然后找到這個索引表位置之后,根據地址表所填地址的數組所在的項數填入索引表中(數組項數依然從0開始算)。(即case值用來找索引表里面具體位置,索引表具體位置里面的具體內容得根據地址表來填入)
索引表如下:
因此地址表所對應的索引表的下標+MIN就是case語句的標號值。
找到所對應的地址索引后*4(地址占4字節)+基地址 就可以找到case的地址。
地址表如下:
在索引表中重復出現的值,可以斷定其是switch的結束地址或者是default語句塊的首地址(或者沒有代碼)。。
在case語句塊沒有任何代碼的情況下,索引表中也會出現相同標號。由于case中沒有任何代碼,當執行到它時,則會順序向下,直到發現下一個case語句不為空為止。這時所有沒有代碼的case屬于一段多個case值共用的代碼。索引表中這些case的對應位置處所保存的都是這段共用代碼在地址表中的下標值,所以出現了索引表標號相同的情況。
總結
以上是生活随笔為你收集整理的2020-11-27(switch的优化问题)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 2020-11-25(《深入理解计算机系
- 下一篇: 详解虚函数的实现过程之初探虚表(1)