




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
1、C 語言宏的高級應(yīng)用關(guān) 于 #和 #在 C 語 言 的 宏 中 , #的 功 能 是 將 其 后 面 的 宏 參 數(shù) 進 行 字 符 串 化 操 作 (Stringfication , 簡單說就是在對它所引用的宏變量通過替換后在其左右各加上一個雙引 號。比如下面代碼中的宏:#define WARN_IF(EXP do if (EXP fprintf(stderr, "Warning: " #EXP "n" while(0那么實際使用中會出現(xiàn)下面所示的替換過程:WARN_IF (divider = 0;被替換為do if (divider = 0fprin
2、tf(stderr, "Warning" "divider = 0" "n" while(0;這樣每次 divider (除數(shù)為 0的時候便會在標準錯誤流上輸出一個提示信息。而 #被稱為連接符(concatenator ,用來將兩個 Token 連接為一個 Token 。注意這里連 接的對象是 Token 就行,而不一定是宏的變量。比如你要做一個菜單項命令名和函數(shù)指針 組成的結(jié)構(gòu)體的數(shù)組, 并且希望在函數(shù)名和菜單項命令名之間有直觀的、 名字上的關(guān)系。 那 么下面的代碼就非常實用:struct commandchar * name;vo
3、id (*function (void;#define COMMAND(NAME NAME, NAME # _command / 然后你就用一些預先定義好的命令來方便的初始化一個 command 結(jié)構(gòu)的數(shù)組了:struct command commands = COMMAND(quit,COMMAND(help,.COMMAND 宏在這里充當一個代碼生成器的作用,這樣可以在一定程度上減少代碼密度, 間接地也可以減少不留心所造成的錯誤。我們還可以 n 個 #符號連接 n+1個 Token ,這 個特性也是 #符號所不具備的。比如:#define LINK_MULTIPLE(a,b,c,d a#_
4、#b#_#c#_#dtypedef struct _record_type LINK_MULTIPLE(name,company,position,salary; / 這里這個語句將展開為:/ typedef struct _record_type name_company_position_salary;關(guān)于 . 的使用. 在 C 宏中稱為 Variadic Macro,也就是變參宏。比如:#define myprintf(templt,. fprintf(stderr,templt,_VA_ARGS_/ 或者#define myprintf(templt,args. fprintf(std
5、err,templt,args第一個宏中由于沒有對變參起名,我們用默認的宏 _VA_ARGS_來替代它。第二個宏中, 我們顯式地命名變參為 args ,那么我們在宏定義中就可以用 args 來代指變參了。同 C 語 言的 stdcall 一樣,變參必須作為參數(shù)表的最有一項出現(xiàn)。當上面的宏中我們只能提供第一 個參數(shù) templt 時, C 標準要 求我們必須寫成:myprintf(templt,;的形式。這時的替換過程為:myprintf("Error!n",;替換為:fprintf(stderr,"Error!n",;這是一個語法錯誤,不能正常編譯。這個
6、問題一般有兩個解決方法。首先, GNU CPP提供 的解決方法允許上面的宏調(diào)用寫成:myprintf(templt;而它將會被通過替換變成:fprintf(stderr,"Error!n",;很明顯,這里仍然會產(chǎn)生編譯錯誤(非本例的某些情況下不會產(chǎn)生編譯錯誤 。除了這種方 式外, c99和 GNU CPP都支持下面的宏定義方式:#define myprintf(templt, . fprintf(stderr,templt, #_VAR_ARGS_這時, #這個連接符號充當?shù)淖饔镁褪钱?_VAR_ARGS_為空的時候,消除前面的那個逗 號。那么此時的翻譯過程如下:mypri
7、ntf(templt;被轉(zhuǎn)化為:fprintf(stderr,templt;這樣如果 templt 合法,將不會產(chǎn)生編譯錯誤。錯誤的嵌套-Misnesting宏的定義不一定要有完整的、 配對的括號, 但是為了避免出錯并且提高可讀性, 最好避免這 樣使用。由操作符優(yōu)先級引起的問題-Operator Precedence Problem由于宏只是簡單的替換, 宏的參數(shù)如果是復合結(jié)構(gòu), 那么通過替換之后可能由于各個參數(shù)之 間的操作符優(yōu)先級高于單個參數(shù)內(nèi)部各部分之間相互作用的操作符優(yōu)先級, 如果我們不用括 號保護各個宏參數(shù),可能會產(chǎn)生預想不到的情形。比如:#define ceil_div(x, y (
8、x + y - 1 / y那么a = ceil_div( b & c, sizeof(int ;將被轉(zhuǎn)化為:a = ( b & c + sizeof(int - 1 / sizeof(int;/ 由于 +/-的優(yōu)先級高于 &的優(yōu)先級,那么上面式子等同于:a = ( b & (c + sizeof(int - 1 / sizeof(int;這顯然不是調(diào)用者的初衷。為了避免這種情況發(fā)生,應(yīng)當多寫幾個括號:#define ceil_div(x, y (x + (y - 1 / (y消除多余的分號-Semicolon Swallowing通常情況下,為了使函數(shù)模樣的宏在
9、表面上看起來像一個通常的 C 語言調(diào)用一樣,通常情 況下我們在宏的后面加上一個分號,比如下面的帶參宏:MY_MACRO(x;但是如果是下面的情況:#define MY_MACRO(x /* line 1 */* line 2 */* line 3 */ /.if (condition(MY_MACRO(a;else.這 樣 會 由 于 多 出 的 那 個 分 號 產(chǎn) 生 編 譯 錯 誤 。 為 了 避 免 這 種 情 況 出 現(xiàn) 同 時 保 持MY_MACRO(x;的這種寫法,我們需要把宏定義為這種形式: #define MY_MACRO(x do /* line 1 */ /* line 2 */ /* line 3 */ while(0 這樣只要保證總是使用分號,就不會有任何問題。 Duplication of Side Effects 這里的 Side Effect 是指宏在展開的時候?qū)ζ鋮?shù)可能進行多次 Evaluation(也就是取值) , 但是如果這個宏參數(shù)是一個函數(shù), 那么就有可能被調(diào)用多次從而達到不一致的結(jié)果, 甚至會 發(fā)生更嚴重的錯誤。比如: #define min(X,Y (X > (Y ? (Y : (X /. c = min(a,foo(b; 這時 foo(函數(shù)就被調(diào)用了兩次。為了解決這個潛在的問題,我們應(yīng)
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 哈爾濱醫(yī)科大學《書畫裝裱》2023-2024學年第二學期期末試卷
- 廣東工程職業(yè)技術(shù)學院《工程招投標與概預算》2023-2024學年第二學期期末試卷
- 江蘇航運職業(yè)技術(shù)學院《中學語文教學設(shè)計與技能訓練(二)》2023-2024學年第二學期期末試卷
- 黑龍江司法警官職業(yè)學院《模擬電子技術(shù)課程設(shè)計》2023-2024學年第二學期期末試卷
- 廣東司法警官職業(yè)學院《數(shù)字特效合成》2023-2024學年第二學期期末試卷
- 天津工藝美術(shù)職業(yè)學院《衛(wèi)生檢驗綜合技術(shù)》2023-2024學年第二學期期末試卷
- 東莞職業(yè)技術(shù)學院《計算機與操作系統(tǒng)》2023-2024學年第二學期期末試卷
- 武漢工程科技學院《外國文學名篇》2023-2024學年第二學期期末試卷
- 2025三年級湘教版語文下學期期末知識點歸納復習周末練習單
- PROMIS-評分量表-使用版
- 軟壓光機計算說明
- 森林防火安全責任書(施工隊用)
- 《汽車性能評價與選購》課程設(shè)計
- 35kV絕緣導線門型直線桿
- 水庫應(yīng)急搶險與典型案例分析
- 49式武當太極劍動作方位
- 工程成本分析報告(新)
- 國際學術(shù)會議海報模板16-academic conference poster model
- 經(jīng)典誦讀比賽評分標準【精選文檔】
- 高值耗材參考目錄
- 步兵戰(zhàn)斗動作
評論
0/150
提交評論