版權(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)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2024年項目參與保密協(xié)議
- 2024無縫鋼管行業(yè)專利申請與保護(hù)協(xié)議2篇
- 2024招投標(biāo)與合同管理:知識產(chǎn)權(quán)合同保護(hù)第一課3篇
- 2024年某高速路段建設(shè)引薦服務(wù)協(xié)議
- 2024年股權(quán)變更正規(guī)協(xié)議模板版B版
- 2024年設(shè)備租賃押金借款合同
- 2025餐飲業(yè)食品安全管理體系認(rèn)證合同范本3篇
- 專業(yè)市場2024年度經(jīng)營管理承包合同書版B版
- 2024技術(shù)開發(fā)合作合同技術(shù)指標(biāo)
- 2024食品公司信息安全保密合同
- 人教版五年級上冊四則混合運算300道及答案
- 服裝企業(yè)員工手冊模板范文
- 《低空航空器起降點基礎(chǔ)設(shè)施配置技術(shù)要求》(征求意見稿)
- 2024中輕度游戲全球市場趨勢洞察
- 中國兒童注意缺陷多動障礙ADHD防治指南專家講座
- 部編人教版數(shù)學(xué)二年級下冊課前預(yù)習(xí)單
- 解除勞動合同經(jīng)濟補償協(xié)議書
- 2024年4月自考02799獸醫(yī)臨床醫(yī)學(xué)試題
- 市政工程勞動力計劃
- 印度尼西亞發(fā)展熱帶經(jīng)濟作物的氣候條件評價-以爪哇和蘇門答臘島為例
- 吞咽障礙康復(fù)護(hù)理專家共識
評論
0/150
提交評論