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

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(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ū)懺诎募?include)中。

例12.1.1宏定義與宏替換應(yīng)用。程序定義了一個宏名:SIZE,用來定義數(shù)組str的容量。程序中還使用了系統(tǒng)定義的一個宏名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;}宏替換的另一個常見的應(yīng)用,是語句串的替換。也就是用一個宏名代表一組C語句。編譯時,凡是程序中遇到這個宏名,就用這些語句代替。這相當(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)行。也就是說,在定義宏時,可以引用已有定義的宏名,實現(xiàn)層層替換。例如:#definePI3.14159#defineSPI*r*r#defineL2*S/r

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

程序如下:

#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

需要注意的是,這個程序的語句

printf("r=%f\tS=%f\tL=%f\n",r,S,L);中,兩次出現(xiàn)S和L:在格式字符串中出現(xiàn)了S和L,在輸出項列表中也出現(xiàn)了S和L。C語言規(guī)定,宏名出現(xiàn)在字符串中時,將不看作是宏名,因而也不做宏替換。所以才有如上所示的輸出。例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;}程序的運行結(jié)果為:

1020.000000

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

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

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

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

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

例12.1.5利用上面的帶參數(shù)的宏定義,編寫求兩個數(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;}

也可以將程序中的兩個語句:

max=MAX(a,b);

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

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

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

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

(4)宏替換是不占程序的運行時間的,只占編譯時間。但宏替換增加程序代碼長度。宏替換的次數(shù)越多,程序代碼長度越長。函數(shù)調(diào)用要消耗程序的運行時間,但不使程序變長。靈活恰當(dāng)?shù)剡\用宏替換,可以使源程序顯得簡潔,增加源程序的可讀性。例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;}在以上兩個例子中,宏的形參都用圓括號括起來了。這不是絕對必要的。例如,例12.1.5中宏定義也可以寫成下面的形式:

#definePI3.14159#defineS(r)PI*r*r#defineL(r)2*S(r)/r但是,對于實參為表達(dá)式的情況,上面參數(shù)不帶括號宏定義,可能會給出錯誤的計算結(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ù)為表達(dá)式時,

S(a+b)=S(3)=7.14159,L(a+b)=12.28318顯然結(jié)果是錯的。后者因為實參沒有括號,所以計算過程是:

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

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

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

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

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

#undef

宏名

12.2文件包含所謂文件包含,是指一個源文件將另一個源文件包含到自己的文件之中。

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

#include<文件名>#include"文件名"

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

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

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

return2*sr(r)/r;}

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

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

returnPI*r*r;}

設(shè)計一個含有上述三個頭文件和主函數(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中定義的兩個函數(shù)是嵌套的。即函數(shù)lr()的定義中引用著函數(shù)sr()。函數(shù)sr()定義中還引用著頭文件myin1.h中的宏定義PI。因此,在主函數(shù)文件中,三個包含命令的文件書寫順序,必須是先myin1.h,然后myin3.h,最后是myin2.h。使用包含文件的結(jié)果,本例的源程序由四個文件組成:三個頭文件和一個主程序文件。經(jīng)過編譯預(yù)處理后,三個頭文件被“包含”到主程序文件中,成為程序的組成部分。圖12.1給出本例包含文件處理的情形。

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

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

此命令的一般形式為:

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

#if常量表達(dá)式程序段1#else

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

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常量表達(dá)式1程序段1#elif

常量表達(dá)式2程序段2

……

……#elif

常量表達(dá)式n

程序段n

#endif

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

#ifd

溫馨提示

  • 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)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論