C/C++编程笔记:浅析 C 语言中宏定义的使用,知识点全解
? ? ? ?宏定義是用一個(gè)標(biāo)識(shí)符來(lái)表示一個(gè)字符串,在宏調(diào)用中將用該字符串代替宏名。給程序員提供了便利,使程序更加清晰,便于閱讀和理解,進(jìn)一步提高了程序的運(yùn)行效率,對(duì)于嵌入式系統(tǒng)而言,為了能達(dá)到性能要求,宏是一種很好的代替函數(shù)的方法,但是使用不慎會(huì)得到意外的結(jié)果。
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
宏是C語(yǔ)言中常用的編譯預(yù)處理功能之一。在編程時(shí),可以使用宏來(lái)代替一些常量或表達(dá)式,給程序員提供了便利,使程序更加清晰,便于閱讀和理解,進(jìn)一步提高了程序的運(yùn)行效率。另外,在C語(yǔ)言中,宏是產(chǎn)生內(nèi)嵌代碼的唯一方法,并且可以定義帶參數(shù)的宏,對(duì)于嵌入式系統(tǒng)而言,為了能達(dá)到性能要求,宏是一種很好的代替函數(shù)的方法。但是如果對(duì)宏命令本質(zhì)理解不透徹,在使用時(shí)可能運(yùn)行的結(jié)果與預(yù)期的結(jié)果就會(huì)大相徑庭。下面具體介紹C語(yǔ)言中宏的使用(即宏定義、宏調(diào)用、宏展開(kāi))。
一、宏定義
在C語(yǔ)言源程序中,允許用一個(gè)標(biāo)識(shí)符表示一個(gè)字符串,稱為“宏”;被定義為宏的標(biāo)識(shí)符稱為“宏名”。
宏定義是由源程序中的宏定義命令完成的。該命令有兩種形式:一種是無(wú)參數(shù)的宏定義;另外一種是帶參數(shù)的宏定義。
(一)無(wú)參數(shù)的宏定義
無(wú)參數(shù)宏的宏名后不帶參數(shù)。其定義的一般形式為:
#define標(biāo)識(shí)符字符串
#是預(yù)處理命令的標(biāo)志,define是宏定義命令的標(biāo)志。標(biāo)識(shí)符為宏名,字符串可以是常量、表達(dá)式、格式串等。
例如:#definePI3.1415926
#defineSUM (1+2)
(二)帶參數(shù)的宏定義
帶參數(shù)的宏定義,也稱為宏函數(shù),在宏定義中的參數(shù)稱為形式參數(shù),形式參數(shù)不分配內(nèi)存單元,所以不必作類型定義。帶參數(shù)的宏定義的一般形式如下:
#define宏名(參數(shù)表)宏體
例如:#defineAREAR(R)3.14*R*R
#define SUM(X,Y) X+Y
兩種格式的宏定義必須寫(xiě)在函數(shù)的外邊,其作用域?yàn)楹甓x命令起到源程序結(jié)束,若要終止其作用域可以用#undef命令加宏名,宏定義也允許嵌套,在宏定義的字符串中可以使用已經(jīng)定義的宏名。
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
二、宏展開(kāi)及宏調(diào)用
(一)宏展開(kāi)及調(diào)用的概念
編譯預(yù)處理時(shí)程序中出現(xiàn)的所有宏名都要有宏定義中的字符串來(lái)代換,稱為宏展開(kāi)。嵌套的宏定義,展開(kāi)時(shí)要層層展開(kāi)。程序中字符串內(nèi)的字符跟宏名相同時(shí)作為一般字符處理,不用宏展開(kāi)。對(duì)于帶參數(shù)的宏的使用稱為宏調(diào)用,一般形式為:宏名(實(shí)參表);在調(diào)用中,不僅要宏展開(kāi),而且要用實(shí)參去代換形參。
C語(yǔ)言源程序的處理過(guò)程,經(jīng)歷了編輯、預(yù)處理、編譯、連接幾個(gè)過(guò)程。其中預(yù)處理產(chǎn)生編譯的輸入,源文件中若有宏命令,則預(yù)處理器將其展開(kāi)成相應(yīng)的宏定義,這個(gè)階段的工作只是純粹的替換展開(kāi),沒(méi)進(jìn)行任何的計(jì)算。同時(shí)現(xiàn)有的編譯系統(tǒng)沒(méi)有提供獨(dú)立的預(yù)處理系統(tǒng)進(jìn)行預(yù)處理,所以我們看不到預(yù)處理后的代碼,在編譯時(shí)可能會(huì)出現(xiàn)錯(cuò)誤,但是系統(tǒng)檢測(cè)不出來(lái)。所以在宏展開(kāi)時(shí)我們一定要謹(jǐn)慎。
(二)宏展開(kāi)及調(diào)用的應(yīng)用實(shí)例
1.無(wú)參宏的定義實(shí)例
例題1:求圓的周長(zhǎng)及面積。
源程序:
#definePI3.14159
main()
{float r,c,s;
scanf(“%f”,&r);
c=2*PI*r;
s=PI*r*r;
printf(“周長(zhǎng)為:%f,面積為:%f”,c,s);}
本題中的PI為宏名,在程序中出現(xiàn)宏名的地方直接用字符串3.14159代替即可得宏展開(kāi)后的程序,并能計(jì)算出結(jié)果。
例題2:源程序:
#defineN2+1
main()
{int a;
a=N*N;
Printf( % d,a); }
本題中宏名N代表的是表達(dá)式2+1,使用時(shí)容易產(chǎn)生的錯(cuò)誤是先把N計(jì)算出來(lái)2+1=3,然后再帶入求a的值,a=3*3,結(jié)果為9。但實(shí)際上宏展開(kāi)只是簡(jiǎn)單的代替,不進(jìn)行計(jì)算,本題應(yīng)該這樣計(jì)算a=2+1*2+1,得到結(jié)果為5。
2.帶參宏的定義實(shí)例
例題3:源程序:
#define f(x)(x*x)
main()
{inti1, i2;
i1=f(8)/f(4);
i2=f(4+4)/f(2+2);
Printf(%d,%d,i1,i2);}
本題的輸出結(jié)果是4,3。i1,i2看上去參數(shù)一樣為什么結(jié)果不同呢,實(shí)際上二者的調(diào)用、展開(kāi)形式不同,其中i1=(8*8)/(4*4)=64/16=4,i2=(4+4*4+4)/(2+2*2+2)=24/8=3;和例題2一樣宏展開(kāi)只是簡(jiǎn)單的代替,不先進(jìn)行計(jì)算。
3.宏使用中問(wèn)題的解決方法。若想正確的使用好宏,應(yīng)當(dāng)做到如下兩方面:一方面在讀別人的程序時(shí),先將程序中對(duì)宏的使用全部替換成它所代表的字符串,不要添加任何其他符號(hào),完全展開(kāi)后再進(jìn)行計(jì)算。另一方面在自己編程時(shí),簡(jiǎn)單的無(wú)參宏定義中當(dāng)字符串中不只一個(gè)字符時(shí),加上括號(hào)表現(xiàn)出優(yōu)先級(jí),帶參的宏定義則要給宏體中的每一個(gè)參數(shù)加上括號(hào),并在整個(gè)宏體上再加上一個(gè)括號(hào)。
看到這里有人不禁會(huì)想,宏使用時(shí)那么麻煩、謹(jǐn)慎,我們?yōu)槭裁催€要使用它,把它擯棄掉算了。但是宏定義的使用有很多的好處。
三、宏定義的優(yōu)點(diǎn)
(一)簡(jiǎn)化程序提高可讀性
使用宏可以將程序中的常量用有意義的符號(hào)代替,當(dāng)常量比較長(zhǎng)時(shí), 以用較短的有意義的標(biāo)識(shí)符來(lái)寫(xiě)程序, 這樣更方便一些。當(dāng)常量值需要改變時(shí),不必在整個(gè)程序中查找常量,只需改變宏定義就可以方便地修改常量值,因此程序修改方便;使程序更加清晰,便于閱讀和理解; 所說(shuō)的常量改變不是在程序運(yùn)行期間改變而是在編程期間的修改。
(二)提高程序的運(yùn)行效率
更為有效的是C語(yǔ)言允許帶參數(shù)宏定義,C語(yǔ)言帶參數(shù)宏定義可以代替簡(jiǎn)單的函數(shù),完成類似函數(shù)調(diào)用的功能。雖然函數(shù)的使用可以使程序更加模塊化,便于組織,而且可重復(fù)利用。但在函數(shù)調(diào)用時(shí),需要保留調(diào)用函數(shù)的現(xiàn)場(chǎng),以便子函數(shù)執(zhí)行結(jié)束后能返回繼續(xù)執(zhí)行,同樣在子函數(shù)執(zhí)行完后要恢復(fù)調(diào)用函數(shù)的現(xiàn)場(chǎng),這都需要一定的時(shí)間。如果子函數(shù)執(zhí)行的操作比較多,這種轉(zhuǎn)換時(shí)間就會(huì)更大,而參數(shù)宏定義在宏調(diào)用展開(kāi)后相當(dāng)于直接嵌入代碼 ,比函數(shù)調(diào)用具有更高的時(shí)間效率。使用帶參數(shù)的宏,不占有內(nèi)存,即能減少系統(tǒng)內(nèi)存的使用,提高運(yùn)行效率。
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
四、結(jié)束語(yǔ)
本文對(duì)C語(yǔ)言中宏定義的使用進(jìn)行了分析,并從C語(yǔ)言源程序處理過(guò)程的角度對(duì)宏的處理進(jìn)行了分析,提出了避免錯(cuò)誤的方法,也對(duì)它的優(yōu)點(diǎn)進(jìn)行了闡述。只要能夠理解宏展開(kāi)的規(guī)則,就能夠體會(huì)宏使用帶來(lái)的方便和效率了。
? ? ? ? 學(xué)習(xí)C/C++編程知識(shí),歡迎關(guān)注博主,一起來(lái)學(xué)習(xí)C語(yǔ)言C++吧!
總結(jié)
以上是生活随笔為你收集整理的C/C++编程笔记:浅析 C 语言中宏定义的使用,知识点全解的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 反向压力!
- 下一篇: CreateChildControls