龔松顯,董銳,劉躍宣
(總參通信訓練基地 教研部,宣化075100)
在單片機程序中,諸如鍵盤按鍵掃描、菜單處理等多種邏輯功能,在代碼上常采用Switch/Case語句的實現方式。Switch/Case語句是一種簡單、初級的邏輯表達式,當代碼較為復雜時,不利于程序的功能調試和邏輯修改[1],程序的可擴充性和可移植性都受到影響。為了在單片機常用的結構化程序設計中避免Switch/Case語句過于冗長,提出一種使用函數指針來替代Switch/Case語句的實現思路,并給出兩種情況下的代碼模型。事實證明,該方法可使程序的結構清晰、易于維護,可提高單片機程序的可讀性和設計效率。
Switch/Case是C語言中的基本語句,其使用方法在大量教材及書籍中均有介紹[2],這里不再贅述。一般來說,Switch/Case語句代碼模型如下:


在該代碼模型中,假定function函數形參及返回值均為void類型,其使用Switch/Case分支語句進行不同情況下的程序處理。Prm Value是從前面的程序處理代碼中獲得的表達式,Prm_A、Prm_B和Prm_C等常量是表達式的值。當表達式的值與某一個Case后面的常量表達式的值匹配時,就執行此Case后面的語句。
從模型上可以看出,對于簡單的功能實現,Switch/Case語句清晰、簡便;但當項目功能較為復雜,例如鍵盤數或菜單級數較多時[3],Switch/Case語句的判斷分支較多,導致代碼冗長,常常一個Case分支語句動輒跨越數十行,程序整體的可讀性和可移植性降低,程序的結構不夠清晰。另外,當Switch/Case語句需要擴展功能時,需要在已經臃腫的Case分支上繼續“添磚加瓦”,造成了程序語句的進一步冗長,不便于后期程序邏輯功能的修改。
在Switch/Case語句代碼模型中,較為常見的一種情況是:Prm_A、Prm_B、Prm_C等常量是連續的數值。對于這種情況,設計思路是定義相關的函數指針數組[4],然后實現相對應的函數。在使用時,只需調用對應的函數指針數組元素即可。該方式下代碼模型如下:

在該代碼模型中,假定函數指針指向的函數形參及返回值均為void類型,Prm Value是從前面的程序處理代碼中獲得的表達式。設計方法中,將每個Case分支的處理代碼封裝成函數,并將每個函數地址按照Case表達式的值的順序賦給函數指針數組各元素。在功能代碼中,程序的實現主體只需使用Prm Value的值調用對應的處理函數即可,原本冗長的Switch/Case語句被一條簡單的函數指針調用代替,形式較為簡潔。使用這種設計方法,當程序需要擴展新的功能邏輯的時候,只需要依次增加函數指針數組元素的值并實現對應的函數,功能代碼的主體部分不需改動。需要注意的一點是,第2種的代碼模型中,假定Prm Value的值是從0開始的,對于Case表達式的值不是從0開始但Case表達式的值連續的情況,上面的代碼模型仍然可以使用。例如,如果Case表達式的值是從delta開始的,在這種情況下只需要將第2種代碼模型中的(p Fun[Prm Value])()表達式改為(p Fun[Prm Valuedelta])()即可,代碼的其他部分均可以保持不變。
第1種代碼模型中,在Prm_A、Prm_B、Prm_C等數值相差較大且不連續的情況下,如果仍然套用2.1節的設計方法,函數指針數組中需要人為填充大量冗余數據,造成資源的浪費,并且在修改時需要做到精確的一一對應,程序的設計反而變得更為麻煩,失去了設計方法的本意。此時需要對第2種代碼模型進行增強設計。其設計思路是通過構建一個數據結構,將離散的Case表達式的值和對應的處理函數一一對應,在功能代碼中對函數指針進行輪詢操作。其實現模型如下:

在該代碼模型中,構建的StructFun結構體數組實現了Case表達式的值和函數指針的一一對應。當程序需要擴展新的功能邏輯時,只需要添加StructFun結構體數組的內容并實現對應函數體即可,設計方法的優點與2.1節的設計方法類似。實際上,2.1節的設計方法是特殊情況下本設計方法的退化,兩種設計方法在思路上仍是保持一致的。
本文介紹的兩種使用函數指針替代Switch/Case語句的方法,使程序的任務處理邏輯關系變得簡潔明了,易于增加程序狀態,更改程序邏輯,程序的可讀性、可調試性強,減少了單片機程序設計中的錯誤。筆者在工程項目中驗證了這兩種設計方法,實際可行且快捷有效,對于單片機常用的結構化程序開發具有一定的借鑒意義。
[1]張臘明,佟宇.狀態機技術在數據通訊協議棧中的編程應用[J].現代電子技術,2008(3):146-147.
[2]譚浩強.C程序設計[M].3版.北京:清華大學出版社,2008.
[3]汪高勇,宋毅恒,尚舉邦.C51與單片機系統多級菜單的模塊化設計[J].光電技術應用,2009,24(2):62-66.
[4]朱博,許倫輝.Keil C51中函數指針的使用[J].單片機與嵌入式系統應用,2008(5):71-72.