龔松顯,董銳,劉躍宣
(總參通信訓(xùn)練基地 教研部,宣化075100)
在單片機(jī)程序中,諸如鍵盤按鍵掃描、菜單處理等多種邏輯功能,在代碼上常采用Switch/Case語句的實(shí)現(xiàn)方式。Switch/Case語句是一種簡(jiǎn)單、初級(jí)的邏輯表達(dá)式,當(dāng)代碼較為復(fù)雜時(shí),不利于程序的功能調(diào)試和邏輯修改[1],程序的可擴(kuò)充性和可移植性都受到影響。為了在單片機(jī)常用的結(jié)構(gòu)化程序設(shè)計(jì)中避免Switch/Case語句過于冗長(zhǎng),提出一種使用函數(shù)指針來替代Switch/Case語句的實(shí)現(xiàn)思路,并給出兩種情況下的代碼模型。事實(shí)證明,該方法可使程序的結(jié)構(gòu)清晰、易于維護(hù),可提高單片機(jī)程序的可讀性和設(shè)計(jì)效率。
Switch/Case是C語言中的基本語句,其使用方法在大量教材及書籍中均有介紹[2],這里不再贅述。一般來說,Switch/Case語句代碼模型如下:
在該代碼模型中,假定function函數(shù)形參及返回值均為void類型,其使用Switch/Case分支語句進(jìn)行不同情況下的程序處理。Prm Value是從前面的程序處理代碼中獲得的表達(dá)式,Prm_A、Prm_B和Prm_C等常量是表達(dá)式的值。當(dāng)表達(dá)式的值與某一個(gè)Case后面的常量表達(dá)式的值匹配時(shí),就執(zhí)行此Case后面的語句。
從模型上可以看出,對(duì)于簡(jiǎn)單的功能實(shí)現(xiàn),Switch/Case語句清晰、簡(jiǎn)便;但當(dāng)項(xiàng)目功能較為復(fù)雜,例如鍵盤數(shù)或菜單級(jí)數(shù)較多時(shí)[3],Switch/Case語句的判斷分支較多,導(dǎo)致代碼冗長(zhǎng),常常一個(gè)Case分支語句動(dòng)輒跨越數(shù)十行,程序整體的可讀性和可移植性降低,程序的結(jié)構(gòu)不夠清晰。另外,當(dāng)Switch/Case語句需要擴(kuò)展功能時(shí),需要在已經(jīng)臃腫的Case分支上繼續(xù)“添磚加瓦”,造成了程序語句的進(jìn)一步冗長(zhǎng),不便于后期程序邏輯功能的修改。
在Switch/Case語句代碼模型中,較為常見的一種情況是:Prm_A、Prm_B、Prm_C等常量是連續(xù)的數(shù)值。對(duì)于這種情況,設(shè)計(jì)思路是定義相關(guān)的函數(shù)指針數(shù)組[4],然后實(shí)現(xiàn)相對(duì)應(yīng)的函數(shù)。在使用時(shí),只需調(diào)用對(duì)應(yīng)的函數(shù)指針數(shù)組元素即可。該方式下代碼模型如下:
在該代碼模型中,假定函數(shù)指針指向的函數(shù)形參及返回值均為void類型,Prm Value是從前面的程序處理代碼中獲得的表達(dá)式。設(shè)計(jì)方法中,將每個(gè)Case分支的處理代碼封裝成函數(shù),并將每個(gè)函數(shù)地址按照Case表達(dá)式的值的順序賦給函數(shù)指針數(shù)組各元素。在功能代碼中,程序的實(shí)現(xiàn)主體只需使用Prm Value的值調(diào)用對(duì)應(yīng)的處理函數(shù)即可,原本冗長(zhǎng)的Switch/Case語句被一條簡(jiǎn)單的函數(shù)指針調(diào)用代替,形式較為簡(jiǎn)潔。使用這種設(shè)計(jì)方法,當(dāng)程序需要擴(kuò)展新的功能邏輯的時(shí)候,只需要依次增加函數(shù)指針數(shù)組元素的值并實(shí)現(xiàn)對(duì)應(yīng)的函數(shù),功能代碼的主體部分不需改動(dòng)。需要注意的一點(diǎn)是,第2種的代碼模型中,假定Prm Value的值是從0開始的,對(duì)于Case表達(dá)式的值不是從0開始但Case表達(dá)式的值連續(xù)的情況,上面的代碼模型仍然可以使用。例如,如果Case表達(dá)式的值是從delta開始的,在這種情況下只需要將第2種代碼模型中的(p Fun[Prm Value])()表達(dá)式改為(p Fun[Prm Valuedelta])()即可,代碼的其他部分均可以保持不變。
第1種代碼模型中,在Prm_A、Prm_B、Prm_C等數(shù)值相差較大且不連續(xù)的情況下,如果仍然套用2.1節(jié)的設(shè)計(jì)方法,函數(shù)指針數(shù)組中需要人為填充大量冗余數(shù)據(jù),造成資源的浪費(fèi),并且在修改時(shí)需要做到精確的一一對(duì)應(yīng),程序的設(shè)計(jì)反而變得更為麻煩,失去了設(shè)計(jì)方法的本意。此時(shí)需要對(duì)第2種代碼模型進(jìn)行增強(qiáng)設(shè)計(jì)。其設(shè)計(jì)思路是通過構(gòu)建一個(gè)數(shù)據(jù)結(jié)構(gòu),將離散的Case表達(dá)式的值和對(duì)應(yīng)的處理函數(shù)一一對(duì)應(yīng),在功能代碼中對(duì)函數(shù)指針進(jìn)行輪詢操作。其實(shí)現(xiàn)模型如下:
在該代碼模型中,構(gòu)建的StructFun結(jié)構(gòu)體數(shù)組實(shí)現(xiàn)了Case表達(dá)式的值和函數(shù)指針的一一對(duì)應(yīng)。當(dāng)程序需要擴(kuò)展新的功能邏輯時(shí),只需要添加StructFun結(jié)構(gòu)體數(shù)組的內(nèi)容并實(shí)現(xiàn)對(duì)應(yīng)函數(shù)體即可,設(shè)計(jì)方法的優(yōu)點(diǎn)與2.1節(jié)的設(shè)計(jì)方法類似。實(shí)際上,2.1節(jié)的設(shè)計(jì)方法是特殊情況下本設(shè)計(jì)方法的退化,兩種設(shè)計(jì)方法在思路上仍是保持一致的。
本文介紹的兩種使用函數(shù)指針替代Switch/Case語句的方法,使程序的任務(wù)處理邏輯關(guān)系變得簡(jiǎn)潔明了,易于增加程序狀態(tài),更改程序邏輯,程序的可讀性、可調(diào)試性強(qiáng),減少了單片機(jī)程序設(shè)計(jì)中的錯(cuò)誤。筆者在工程項(xiàng)目中驗(yàn)證了這兩種設(shè)計(jì)方法,實(shí)際可行且快捷有效,對(duì)于單片機(jī)常用的結(jié)構(gòu)化程序開發(fā)具有一定的借鑒意義。
[1]張臘明,佟宇.狀態(tài)機(jī)技術(shù)在數(shù)據(jù)通訊協(xié)議棧中的編程應(yīng)用[J].現(xiàn)代電子技術(shù),2008(3):146-147.
[2]譚浩強(qiáng).C程序設(shè)計(jì)[M].3版.北京:清華大學(xué)出版社,2008.
[3]汪高勇,宋毅恒,尚舉邦.C51與單片機(jī)系統(tǒng)多級(jí)菜單的模塊化設(shè)計(jì)[J].光電技術(shù)應(yīng)用,2009,24(2):62-66.
[4]朱博,許倫輝.Keil C51中函數(shù)指針的使用[J].單片機(jī)與嵌入式系統(tǒng)應(yīng)用,2008(5):71-72.