C語言的預(yù)處理器課件_第1頁
C語言的預(yù)處理器課件_第2頁
C語言的預(yù)處理器課件_第3頁
C語言的預(yù)處理器課件_第4頁
C語言的預(yù)處理器課件_第5頁
已閱讀5頁,還剩56頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

C語言的預(yù)處理器

編譯預(yù)處理命令不是C語言的語句,它的作用只是告訴(命令)編譯系統(tǒng),在編譯根源程式之前對根源程式進(jìn)行某種預(yù)加工,而後再進(jìn)行編譯。所有的編譯預(yù)處理命令都是以符號“#”開頭,末尾不加分號。預(yù)處理命令可以用在程式的任何地方。本章主要介紹以下的C語言的編譯預(yù)處理命令:宏定義的命令:#define,#undef;檔包含命令:#include;條件編譯命令:#if_#else_#endif;

#if_#elif_#endif;

#ifdef_#else_#endif;

#ifndef_#else_#endif。

12.1宏定義和宏替換12.1.1不帶參數(shù)的宏定義和引用

不帶參數(shù)的宏定義的一般形式為:

#define宏名字元序列 宏定義的作用是,在對根源程式編譯之前,將程式中出現(xiàn)的所有的宏名用對應(yīng)的字元序列來代替。這種替換稱宏替換或宏引用。不帶參數(shù)宏替換,通常的用途是,用宏名定義程式中的常量,如:

#defineFALSE0#defineWORDS"TurboC++"

通常把宏定義寫在檔的開始部分,函數(shù)的外面,或?qū)懺诎瑱n(#include)中。

例12.1.1宏定義與宏替換應(yīng)用。程式定義了一個(gè)宏名:SIZE,用來定義數(shù)組str的容量。程式中還使用了系統(tǒng)定義的一個(gè)宏名NULL(空字元),用於檢查字元型數(shù)組中字串的結(jié)束符。程式的功能是,將用戶輸入的字串存入數(shù)組str,然後,變成大寫字母將其輸出。

程式如下:

#include"stdio.h"#defineSIZE80 /*宏定義SIZE*/main(){

inti;charstr[SIZE];/*宏SIZE的引用*/

printf("Enterastring:");gets(str);

for(i=0;str[i]!=NULL;i++) /*宏NULL的引用*/

printf("%c",toupper(str[i]));

printf("\n");return;}宏替換的另一個(gè)常見的應(yīng)用,是語句串的替換。也就是用一個(gè)宏名代表一組C語句。編譯時(shí),凡是程式中遇到這個(gè)宏名,就用這些語句代替。這相當(dāng)於調(diào)用無參數(shù)的函數(shù)。例12.1.2求1~num之間的質(zhì)數(shù)的程式。程式中使用了如下的C語句宏定義:

#definePRIMEfor(i=2;i<n;i++)\if(n%i==0)prime=0;

程式如下:

#include"stdio.h"#definePRIMEfor(i=2;i<n;i++)\if(n%i==0)prime=0; /*宏定義*/

main(){

intn,i,prime,num,k=0;

printf("Enteranumber:");

scanf("%d",&num);

for(n=2;n<num;n++){prime=1;PRIME; /*宏替換*/

if(prime){

printf("%4d",n);if(!(++k%5))printf("\n");}}

printf("\n");return0;}

宏定義可以嵌套進(jìn)行。也就是說,在定義宏時(shí),可以引用已有定義的宏名,實(shí)現(xiàn)層層替換。例如:#definePI3.14159#defineSPI*r*r#defineL2*S/r

其中定義S時(shí),使用了已定義的PI;定義L時(shí),使用了已定義的S。例12.1.3應(yīng)用上面嵌套結(jié)構(gòu)的宏定義,計(jì)算圓的面積和周長。

程式如下:

#include"stdio.h"#definePI3.14159#defineSPI*r*r#defineL2*S/rmain(){

floatr;

printf("Enterr:");

scanf("%f",&r);

printf("r=%f\tS=%f\tL=%f\n",r,S,L);

return;}程式輸出舉例(帶下劃線的數(shù)據(jù)是用戶輸入的):

Enterr:1r=1.000000S=3.141590L=6.283180

需要注意的是,這個(gè)程式的語句

printf("r=%f\tS=%f\tL=%f\n",r,S,L);中,兩次出現(xiàn)S和L:在格式字串中出現(xiàn)了S和L,在輸出項(xiàng)列表中也出現(xiàn)了S和L。C語言規(guī)定,宏名出現(xiàn)在字串中時(shí),將不看作是宏名,因而也不做宏替換。所以才有如上所示的輸出。例12.1.4將宏用於輸出語句中的例子。

#include"stdio.h"#definePRNprintf/*定義宏*/#defineD"%d\n"#defineF"%f\n"#defineS"%s\n"main(){

inti=10;floatf=20.0;charch[]="string.";

PRN(D,i);PRN(F,f);PRN(S,ch);

return;}程式的運(yùn)行結(jié)果為:

1020.000000

string.12.1.2帶參數(shù)的宏定義和引用帶參數(shù)的宏定義的一般形式為:

#define宏名(形參表)字元序列

程式中引用宏名時(shí),寫入實(shí)參,就像函數(shù)調(diào)用那樣。定義了宏名後,編譯系統(tǒng)在開始編譯根源程式前,把程式中引用的宏替換成相應(yīng)的一串符號,然後進(jìn)行編譯。在替換過程中用實(shí)參代替形參。

下麵是一個(gè)帶參數(shù)的宏定義的例子:

#defineMAX(a,b)((a)>(b))?(a):(b)

例12.1.5利用上面的帶參數(shù)的宏定義,編寫求兩個(gè)數(shù)中的較大者的程式。程式如下:#include"stdio.h"#defineMAX(a,b)((a)>(b))?(a):(b) /*宏定義*/

main(){

inta,b,max;

printf("Enter2numbers:");

scanf("%d%d",&a,&b);

max=MAX(a,b); /*宏替換*/

printf("Themanximumnum=%d\n",max);

return0;}

也可以將程式中的兩個(gè)語句:

max=MAX(a,b);

printf("Themanximumnum=%d",max);寫成如下的一個(gè)語句:

printf("Themanximumnum=%d",MAX(a,b));

其效果是一樣的。我們看到,這種宏替換很象調(diào)用函數(shù)。例如:

max=MAX(a,b);MAX(a,b);但它們的工作的機(jī)理是完全不同的,在概念更上不要混淆。它們之間的不同,體現(xiàn)在以下四個(gè)方面。(1)函數(shù)調(diào)用時(shí),要計(jì)算實(shí)參並向形參傳送。而宏中的參數(shù),只是進(jìn)行簡單的替換。既沒有向形參拷貝數(shù)據(jù),也沒有傳送參數(shù)地址。(2)函數(shù)中的實(shí)參和形參有確定數(shù)據(jù)類型,並且兩者是一一對應(yīng)的。宏名沒有數(shù)據(jù)類型。它只是個(gè)符號。其參數(shù)也只是個(gè)符號而已。引用時(shí),代入指定的字元。宏定義的字串可以是任何數(shù)據(jù)類型。(3)宏是在編譯時(shí)進(jìn)行替換的,不分配記憶體空間。而函數(shù)調(diào)用是在程式運(yùn)行時(shí)處理的,並分配相應(yīng)的臨時(shí)的記憶體空間。

(4)宏替換是不占程式的運(yùn)行時(shí)間的,只占編譯時(shí)間。但宏替換增加程式代碼長度。宏替換的次數(shù)越多,程式代碼長度越長。函數(shù)調(diào)用要消耗程式的運(yùn)行時(shí)間,但不使程式變長。靈活恰當(dāng)?shù)剡\(yùn)用宏替換,可以使根源程式顯得簡潔,增加根源程式的可讀性。例12.1.6編寫程式,將例12.1.3中無參數(shù)宏定義改為帶參數(shù)r的宏定義:

#defineS(r)PI*(r)*(r)#defineL(r)2*S(r)/(r)

程式如下:

#include"stdio.h"#definePI3.14159 /*定義不帶參數(shù)的宏*/#defineS(r)PI*(r)*(r) /*定義帶參數(shù)r的宏*/#defineL(r)2*S(r)/(r) /*定義帶參數(shù)r的宏*/

main(){

floatr;

printf("Enterr:");

scanf("%f",&r);

printf("r=%f\tS=%f\tL=%f\n",r,S(r),L(r)); /*宏的引用*/

return;}在以上兩個(gè)例子中,宏的形參都用圓括號括起來了。這不是絕對必要的。例如,例12.1.5中宏定義也可以寫成下麵的形式:

#definePI3.14159#defineS(r)PI*r*r#defineL(r)2*S(r)/r但是,對於實(shí)參為運(yùn)算式的情況,上面參數(shù)不帶括弧宏定義,可能會給出錯誤的計(jì)算結(jié)果。設(shè)有r=3.0.a=1.0.b=2.0

根據(jù)上面的宏定義,則有:

S(r)=s(3)=28.27431,L(r)=l(3)18.84954

而參數(shù)為運(yùn)算式時(shí),

S(a+b)=S(3)=7.14159,L(a+b)=12.28318顯然結(jié)果是錯的。後者因?yàn)閷?shí)參沒有括弧,所以計(jì)算過程是:

S(a+b)=3.14159×1+2×1+2=3.14159+2+2=7.14159

如果在宏定義裏給參數(shù)r加上括弧,則計(jì)算過程是:

S(a+b)=3.14159×(1+2)×(1+2)=3.14159×3×3=28.27431

結(jié)果是正確的。為了避免出現(xiàn)上述可能出現(xiàn)的錯誤,在定義帶參數(shù)的宏時(shí),最好給參數(shù)加上圓括號。

12.1.3取消宏定義#undef命令用於取消先前已定義的宏名。其一般形式為:

#undef

宏名

12.2文件包含所謂檔包含,是指一個(gè)原始檔案將另一個(gè)原始檔案包含到自己的檔之中。

檔包含命令有如下兩種形式:

#include<檔案名>#include"檔案名"

包含命令的功能是,在編譯預(yù)處理時(shí),用命令指定的檔案名的文本內(nèi)容來替代該命令,使包含檔的內(nèi)容成為本程式的一部分。

如果檔案名用了雙引號,則首先查找當(dāng)前目錄,若找不到該檔,則查找命令行定義的其他目錄。如果仍找不到該檔,則查找系統(tǒng)定義的標(biāo)準(zhǔn)目錄。如果檔案名使用了尖括弧,則編譯器首先查找命令行指定的目錄;如果找不到該檔,則查找標(biāo)準(zhǔn)目錄,不查找當(dāng)前工作目錄。例12.2.1給定半徑,計(jì)算圓的周長和圓面積。為了展示利用檔包含命令處理多檔程式的設(shè)計(jì)方法,我們設(shè)計(jì)三個(gè)如下的包含檔,或稱頭檔:頭檔1名為myin1.h。檔內(nèi)容包含如下兩條:#include<stdio.h>#definePI3.14159 /*宏定義PI*/頭檔2名為myin2.h。其內(nèi)容是函數(shù)lr的定義:

floatlr(floatr) /*計(jì)算圓周長的函數(shù)*/{

return2*sr(r)/r;}

頭檔3名為myin3.h。檔內(nèi)容是函數(shù)sr的定義。

floatsr(floatr) /*計(jì)算圓面積的函數(shù)*/{

returnPI*r*r;}

設(shè)計(jì)一個(gè)含有上述三個(gè)頭檔和主函數(shù)程式如下:#include"myin1.h"#include"myin3.h"#include"myin2.h"main(){floatx=3.0;

printf("L=%f\n",lr(x));

printf("S=%f\n",sr(x));}這裏在檔myin3.h和文件myin2.h中定義的兩個(gè)函數(shù)是嵌套的。即函數(shù)lr()的定義中引用著函數(shù)sr()。函數(shù)sr()定義中還引用著頭檔myin1.h中的宏定義PI。因此,在主函數(shù)檔中,三個(gè)包含命令的檔書寫順序,必須是先myin1.h,然後myin3.h,最後是myin2.h。使用包含檔的結(jié)果,本例的根源程式由四個(gè)檔組成:三個(gè)頭檔和一個(gè)主程序檔。經(jīng)過編譯預(yù)處理後,三個(gè)頭檔被“包含”到主程序檔中,成為程式的組成部分。圖12.1給出本例包含檔處理的情形。

圖12.1例12.2.1包含檔處理示意圖12.3條件編譯C語言的條件編譯預(yù)處理命令就是用於有選擇的編譯根源程式中某些部分的。條件編譯主要用於調(diào)試程式。條件編譯的另一個(gè)用途是,可以用根源程式產(chǎn)生不同版本。

12.3.1#if_#endif類型的條件編譯命令這是根據(jù)運(yùn)算式的值進(jìn)行條件編譯的命令。該條件編譯命令有以下三種不同形式。1.#if_#endif

此命令的一般形式為:

#if常數(shù)運(yùn)算式程式段#endif其作用是,如果常數(shù)運(yùn)算式為真,則編譯從#if到#endif之間的程式段(活語句塊);否則就不編譯,跳過這段程式。2.#if_#else_#endif此命令的一般形式為:

#if常量運(yùn)算式程式段1#else

程式段2#endif其作用是,如果常量運(yùn)算式為真,編譯程序段1的代碼段;否則,編譯程序段2的代碼段。例12.3.1用戶給定一整數(shù)MAX。當(dāng)MAX大於或等於100時(shí),編譯語句:

printf("MAX>=100");

否則,編譯語句:

printf("MAX<100");程式如下:

#include<stdio.h>#defineMAX120main(){#ifMAX>=100

printf("MAX>=100\n");#else

printf("MAX<100\n");

#endif

printf("MAX=%d\n",MAX);return0;}3.#if_#elif_#endif

這是用於多路選擇的編譯命令。它的一般形式為:

#if常量運(yùn)算式1程式段1#elif

常量運(yùn)算式2程式段2

……

……#elif

常量運(yùn)算式n

程式段n

#endif

其作用是,如果常量運(yùn)算式1為真,則編譯程序段1;否則,如果常量運(yùn)算式2為真,則編譯程序段2;否則,如果常量運(yùn)算式3為真,則編譯程序段3;直到最後,如果常量運(yùn)算式n為真,則編譯程序段n。12.3.2#ifdef和#ifndef類型的條件編譯命令這是根據(jù)識別字的定義與否進(jìn)行條件編譯的命令。識別字是用宏定義命令實(shí)現(xiàn)的。因此,也可以說,這種條件編譯是根據(jù)宏名是否被定義決定某程式段是否進(jìn)行編譯。這種條件編譯預(yù)處理命令有兩種格式。1.#ifdef_#endif類型條件編譯命令這種類型的命令有以下兩種格式:第一種格式為:

#ifdef

溫馨提示

  • 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)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論