![C語言宏的高級應(yīng)用_百度文庫_第1頁](http://file3.renrendoc.com/fileroot_temp3/2022-2/26/1dc9d2ba-a96c-4933-819b-fb938d36987a/1dc9d2ba-a96c-4933-819b-fb938d36987a1.gif)
![C語言宏的高級應(yīng)用_百度文庫_第2頁](http://file3.renrendoc.com/fileroot_temp3/2022-2/26/1dc9d2ba-a96c-4933-819b-fb938d36987a/1dc9d2ba-a96c-4933-819b-fb938d36987a2.gif)
![C語言宏的高級應(yīng)用_百度文庫_第3頁](http://file3.renrendoc.com/fileroot_temp3/2022-2/26/1dc9d2ba-a96c-4933-819b-fb938d36987a/1dc9d2ba-a96c-4933-819b-fb938d36987a3.gif)
![C語言宏的高級應(yīng)用_百度文庫_第4頁](http://file3.renrendoc.com/fileroot_temp3/2022-2/26/1dc9d2ba-a96c-4933-819b-fb938d36987a/1dc9d2ba-a96c-4933-819b-fb938d36987a4.gif)
![C語言宏的高級應(yīng)用_百度文庫_第5頁](http://file3.renrendoc.com/fileroot_temp3/2022-2/26/1dc9d2ba-a96c-4933-819b-fb938d36987a/1dc9d2ba-a96c-4933-819b-fb938d36987a5.gif)
版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
1、C 語言宏的高級應(yīng)用關(guān) 于 #和 #在 C 語 言 的 宏 中 , #的 功 能 是 將 其 后 面 的 宏 參 數(shù) 進(jìn) 行 字 符 串 化 操 作 (Stringfication , 簡單說就是在對它所引用的宏變量通過替換后在其左右各加上一個(gè)雙引 號。比如下面代碼中的宏:#define WARN_IF(EXP do if (EXP fprintf(stderr, "Warning: " #EXP "n" while(0那么實(shí)際使用中會出現(xiàn)下面所示的替換過程:WARN_IF (divider = 0;被替換為do if (divider = 0fprin
2、tf(stderr, "Warning" "divider = 0" "n" while(0;這樣每次 divider (除數(shù)為 0的時(shí)候便會在標(biāo)準(zhǔn)錯誤流上輸出一個(gè)提示信息。而 #被稱為連接符(concatenator ,用來將兩個(gè) Token 連接為一個(gè) Token 。注意這里連 接的對象是 Token 就行,而不一定是宏的變量。比如你要做一個(gè)菜單項(xiàng)命令名和函數(shù)指針 組成的結(jié)構(gòu)體的數(shù)組, 并且希望在函數(shù)名和菜單項(xiàng)命令名之間有直觀的、 名字上的關(guān)系。 那 么下面的代碼就非常實(shí)用:struct commandchar * name;vo
3、id (*function (void;#define COMMAND(NAME NAME, NAME # _command / 然后你就用一些預(yù)先定義好的命令來方便的初始化一個(gè) command 結(jié)構(gòu)的數(shù)組了:struct command commands = COMMAND(quit,COMMAND(help,.COMMAND 宏在這里充當(dāng)一個(gè)代碼生成器的作用,這樣可以在一定程度上減少代碼密度, 間接地也可以減少不留心所造成的錯誤。我們還可以 n 個(gè) #符號連接 n+1個(gè) Token ,這 個(gè)特性也是 #符號所不具備的。比如:#define LINK_MULTIPLE(a,b,c,d a#_
4、#b#_#c#_#dtypedef struct _record_type LINK_MULTIPLE(name,company,position,salary; / 這里這個(gè)語句將展開為:/ 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第一個(gè)宏中由于沒有對變參起名,我們用默認(rèn)的宏 _VA_ARGS_來替代它。第二個(gè)宏中, 我們顯式地命名變參為 args ,那么我們在宏定義中就可以用 args 來代指變參了。同 C 語 言的 stdcall 一樣,變參必須作為參數(shù)表的最有一項(xiàng)出現(xiàn)。當(dāng)上面的宏中我們只能提供第一 個(gè)參數(shù) templt 時(shí), C 標(biāo)準(zhǔn)要 求我們必須寫成:myprintf(templt,;的形式。這時(shí)的替換過程為:myprintf("Error!n",;替換為:fprintf(stderr,"Error!n",;這是一個(gè)語法錯誤,不能正常編譯。這個(gè)
6、問題一般有兩個(gè)解決方法。首先, 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í), #這個(gè)連接符號充當(dāng)?shù)淖饔镁褪钱?dāng) _VAR_ARGS_為空的時(shí)候,消除前面的那個(gè)逗 號。那么此時(shí)的翻譯過程如下:mypri
7、ntf(templt;被轉(zhuǎn)化為:fprintf(stderr,templt;這樣如果 templt 合法,將不會產(chǎn)生編譯錯誤。錯誤的嵌套-Misnesting宏的定義不一定要有完整的、 配對的括號, 但是為了避免出錯并且提高可讀性, 最好避免這 樣使用。由操作符優(yōu)先級引起的問題-Operator Precedence Problem由于宏只是簡單的替換, 宏的參數(shù)如果是復(fù)合結(jié)構(gòu), 那么通過替換之后可能由于各個(gè)參數(shù)之 間的操作符優(yōu)先級高于單個(gè)參數(shù)內(nèi)部各部分之間相互作用的操作符優(yōu)先級, 如果我們不用括 號保護(hù)各個(gè)宏參數(shù),可能會產(chǎn)生預(yù)想不到的情形。比如:#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)當(dāng)多寫幾個(gè)括號:#define ceil_div(x, y (x + (y - 1 / (y消除多余的分號-Semicolon Swallowing通常情況下,為了使函數(shù)模樣的宏在
9、表面上看起來像一個(gè)通常的 C 語言調(diào)用一樣,通常情 況下我們在宏的后面加上一個(gè)分號,比如下面的帶參宏:MY_MACRO(x;但是如果是下面的情況:#define MY_MACRO(x /* line 1 */* line 2 */* line 3 */ /.if (condition(MY_MACRO(a;else.這 樣 會 由 于 多 出 的 那 個(gè) 分 號 產(chǎn) 生 編 譯 錯 誤 。 為 了 避 免 這 種 情 況 出 現(xiàn) 同 時(shí) 保 持MY_MACRO(x;的這種寫法,我們需要把宏定義為這種形式: #define MY_MACRO(x do /* line 1 */ /* line 2 */ /* line 3 */ while(0 這樣只要保證總是使用分號,就不會有任何問題。 Duplication of Side Effects 這里的 Side Effect 是指宏在展開的時(shí)候?qū)ζ鋮?shù)可能進(jìn)行多次 Evaluation(也就是取值) , 但是如果這個(gè)宏參數(shù)是一個(gè)函數(shù), 那么就有可能被調(diào)用多次從而達(dá)到不一致的結(jié)果, 甚至?xí)?發(fā)生更嚴(yán)重的錯誤。比如: #define min(X,Y (X > (Y ? (Y : (X /. c = min(a,foo(b; 這時(shí) foo(函數(shù)就被調(diào)用了兩次。為了解決這個(gè)潛在的問題,我們應(yīng)
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 機(jī)械設(shè)備海上運(yùn)輸合同范本
- 軟件開發(fā)技術(shù)施工方案
- 室內(nèi)設(shè)計(jì)工作室裝修協(xié)議
- 個(gè)性化咖啡館裝修合同模板
- 親子酒店陽臺裝修合同
- 民宿藝術(shù)館裝修合同范本
- 機(jī)械設(shè)備物流合同范本
- 長寧防靜電地坪施工方案
- 合同范本政府蓋章
- 公寓短租租房合同范例
- 醫(yī)院招標(biāo)采購管理辦法及實(shí)施細(xì)則(試行)
- 初中英語-Unit2 My dream job(writing)教學(xué)設(shè)計(jì)學(xué)情分析教材分析課后反思
- 2023湖南株洲市茶陵縣茶陵湘劇保護(hù)傳承中心招聘5人高頻考點(diǎn)題庫(共500題含答案解析)模擬練習(xí)試卷
- 廣州市勞動仲裁申請書
- 江西省上饒市高三一模理綜化學(xué)試題附參考答案
- 23-張方紅-IVF的治療流程及護(hù)理
- 頂部板式吊耳計(jì)算HGT-20574-2018
- 因數(shù)和倍數(shù)復(fù)習(xí)思維導(dǎo)圖
- LY/T 2986-2018流動沙地沙障設(shè)置技術(shù)規(guī)程
- 三級教育考試卷(電工)答案
- 醫(yī)院標(biāo)準(zhǔn)化運(yùn)營管理課件
評論
0/150
提交評論