版權說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權,請進行舉報或認領
文檔簡介
第八章預處理命令內(nèi)容簡介(1)什么是預處理?(2)如何進行宏定義和宏展開?(3)帶參數(shù)宏定義和函數(shù)的區(qū)別?(4)文件包含的意義?(5)條件編譯的作用和實現(xiàn)方法?本章導讀◎本章導讀在前面各章節(jié)中,已經(jīng)多次出現(xiàn)過以“#”號開頭的預處理命令,如包含命令#include,宏定義命令#define等,其中的“#”表示這是一條預處理命令。凡是以“#”開頭的均為預處理命令。在源程序中這些命令都放在函數(shù)之外,而且一般都放在源文件的前面,它們稱為預處理。所謂預處理是指在對程序進行通常的編譯(詞法、語法分析,代碼生成、優(yōu)化等)之前對其所作的“預先”處理工作。預處理是C語言的一個重要功能,它由預處理程序負責完成。當對一個源文件進行編譯時,系統(tǒng)將自動啟動預處理程序?qū)υ闯绦蛑械念A處理部分作處理,處理完畢后自動進入對源程序的編譯。如圖8-1所示。本章導讀C語言提供了多種預處理功能,如宏定義、文件包含、條件編譯等。合理使用預處理功能編寫的程序便于閱讀、修改、移植和調(diào)試,也有利
于模塊化程序設計。本章介紹常用的幾種預處理功能。C源程序預處理編譯目標程序xx.cxx.obj連接可執(zhí)行程序xx.exe圖8-1
C程序執(zhí)行過程8.1宏定義在C語言源程序中允許用一個標識符來表示一個字符串,稱為宏。被定義為宏的標識符稱為宏名。在編譯預處理時,對程序中所有出現(xiàn)的宏
名,都用宏定義中的字符串去代換,這稱為宏展開或宏替換。宏定義是
由源程序中的宏定義命令完成的,宏展開是由預處理程序自動完成的。
在C語言中,宏分為有參數(shù)和無參數(shù)兩種。下面分別討論這兩種宏的定義和調(diào)用。8.1.1不帶參數(shù)的宏定義不帶參數(shù)宏的宏名后面不帶參數(shù)。其定義的一般形式為:#define
標識符
字符串例:#define
MAX
100功能:定義一個不帶參數(shù)的宏——“標識符”,使其等價于“字符串”,即如8.1宏定義果在程序中見到“標識符”,就用“字符串”替換它?!癲efine”為宏定義命令?!皹俗R符”為所定義的宏名。“字符串”可以是常數(shù)、表達式、格式串。例如:/* 源程序
*/#define
MAX
100*//*
預處理后的新源程序void
main()void
main(){int
a[10].i;{int
a[10].i;for
(i=0;i<10;i++)for
(i=0;i<10;i++){scanf(“%d”,
&a[i]);{scanf(“%d”,
&a[i]);if(a[i]>=MAX)if(a[i]>=100)a[i]-=MAX;a[i]-=
100;}}for
(i=0;i<10;i++)for
(i=0;i<10;i++)printf(“%d
”,
a[i]);printf(“%d
”,
a[i]);}}8.1宏定義說明:習慣上宏名用大寫字母表示,以便于與變量區(qū)別。但也允許用小寫字母;宏定義是用宏名來表示一個字符串,在宏展開時又以該字符串取代宏名,這只是一種簡單的替換,預處理程序?qū)甓x中的“字符串”不作任何檢查。如有錯誤,只能在編譯已被宏展開后的源程序時發(fā)現(xiàn);宏定義不是說明或語句,在行末不必加分號,如加上分號則連同分號一起替換。例如:#define
MAX
100;…if(a[i]>=MAX)
a[i]-=
MAX;則,預處理后的源程序如下所示:if(a[i]>=100;)
a[i]-=
100;;這顯然是有語法錯誤的;8.1宏定義(4)宏定義必須寫在函數(shù)之外,其作用域為宏定義命令起到源程序結束。如果要終止其作用域可使用#undef命令。例如:#define
MAX
100main(){…}#undef
MAXf1(){…}表示MAX只在main函數(shù)中有效,在f1中無效,也就是說,即使在f1中出現(xiàn)了MAX,也不替換成100;8.1宏定義宏定義允許嵌套,在宏定義的字符串中可以使用已經(jīng)定義的宏名,在宏展開時由預處理程序?qū)訉犹鎿Q。例如:#define
PI
3.14159265#define
S
PI*r*r
/*
PI是已定義的宏名*/則語句:printf("%f",S);在宏展開后變?yōu)椋簆rintf("%f",3.1415926*r*r);對于程序中雙引號括起來的字符串中的字符,即使與宏名相同,也不進行宏展開。例如:#define
MAX
100main(){
…printf(“MAX=%d”,MAX);}8.1宏定義其中的printf語句在宏展開后變?yōu)椋簆rintf(“MAX=%d”,100);在進行預處理時,只將printf語句中后面的MAX替換成100,而前面雙引號中的MAX因為是字符串常量的一部分而不被替換?!纠?-1】閱讀下面程序。1#define
SIZE
10/*宏定義*/2#define
FORMAT
“%d”/*宏定義*/3void
main()4{int
a[SIZE],i;5for(i=0;i<SIZE;i++)scanf(FORMAT,&a[i]);for(i=SIZE-1;i>=0;i--)printf(FORMAT,
a[i]);9
}8.1宏定義運行結果:程序說明:在文件開頭設置兩個宏定義,分別對程序中的數(shù)組長度和輸出格式進行控制。如果想改變這兩個量,通過修改宏定義就可以達到目的,一改全改。8.1宏定義【例8-2】閱讀下面程序。#define
N
2#define
M
N+#define
NUM
2*M+1main(){int
i;for(i=1;i<=NUM;i++)printf("%d
",i);7
}8.1宏定義運行結果:程序說明:根據(jù)嵌套宏定義的規(guī)則,宏名M被替換成2+1,繼而宏名NUM被替換成2*2+1+1,因此上例中第6行在預處理后為如下形式:for(i=1;i<=2*2+1+1;i++)printf("%d
",i);所以,循環(huán)語句執(zhí)行了6次。8.1宏定義8.1.2帶參數(shù)的宏定義C語言允許宏定義帶有參數(shù)。在宏定義中的參數(shù)稱為形式參數(shù),在宏調(diào)用中的參數(shù)稱為實際參數(shù)。對帶參數(shù)的宏,在調(diào)用中,不僅要宏展開,而且要用實參去替換宏定義中的形參。帶參數(shù)宏定義的一般形式為:#define
宏名(形式參數(shù)表)
字符串其中,在字符串中含有各個形式參數(shù)。帶參數(shù)宏調(diào)用的一般形式為:宏名(實際參數(shù)表)例如:#define
M(y)
y*y+3*y
/*
宏定義
*/…k=M(5);
/*
宏調(diào)用
*/…8.1宏定義在宏調(diào)用時,用實參5去代替形參y,經(jīng)預處理宏展開后的語句為:k=5*5+3*5;如圖8-2所示。【例8-3】閱讀下面程序。1
#define
MAX(a,b)
(a>b)?a:b#define
M(y)
y*y+3*y…k=M(5);…2main()k=
5*5+3*5;3{int
x,y,max;圖8-2帶參數(shù)宏調(diào)用4printf("input
two
numbers:");5scanf("%d%d",&x,&y);6max=MAX(x,y);7printf("max=%d\n",max);8}8.1宏定義運行結果:程序說明:第1行進行帶參數(shù)的宏定義,用宏名MAX表示條件表達式(a>b)?a:b,形參a,b均出現(xiàn)在條件表達式中。程序第6行max=MAX(x,y)為宏調(diào)用,
實參x、y將替換形參a、b。宏展開后該語句為:max=(x>y)?x:y;用于計算x,y中的最大值。8.1宏定義程序第1
參為a+1,是一個表達式,在宏展開時,用a+1代換y,再用(y)*(y)代換SQ,得到如下語句:sq=(a+1)*(a+1);注意:這與函數(shù)調(diào)用的原理是不同的,函數(shù)調(diào)用時要把實參表達式的值求出來再賦予形參。而宏展開中對實參表達式不作計算直接照原樣替換;/* 源程序
*/#define
SQUARE(y)
(y)*(y)main(){int
a,s;/*
預處理后的新源程序*/main(){int
a,s;printf("input
a
number:
");printf("input
a
number:");scanf("%d",&a);scanf("%d",&a);s=(a+1)*(a+1);s=
SQUARE(a+1);printf("sq=%d\n",s);printf("sq=%d\n",s);
}行}
為宏定義,形參為y。第6行宏調(diào)用中實8.1宏定義(3)在宏定義中,字符串內(nèi)的形參通常要用括號括起來以避免出錯。在上例中的宏定義中(y)*(y)表達式的y都用括號括起來,因此結果是正確的。如果去掉括號,把程序改為以下形式:/* 源程序
*/#define
SQUARE(y)
y*ymain(){int
a,s;printf("input
a
number:
");scanf("%d",&a);s=
SQUARE(a+1);printf("sq=%d\n",s);}/*
預處理后的新源程序*/main(){int
a,s;printf("input
a
number:
");scanf("%d",&a);s=
a+1*a+1;printf("sq=%d\n",s);}8.1宏定義由于宏展開只作簡單的符號替換而不作其它處理,宏展開后將得到以下語句:sq=a+1*a+1;這顯然與題意相違,因此參數(shù)兩邊的括號是不能少的;在帶參數(shù)宏定義中,形式參數(shù)不分配內(nèi)存單元,因此不必作類型定義。而宏調(diào)用中的實參有具體的值。要用它們?nèi)ヌ鎿Q形參,因此必
須作類型說明。這是與函數(shù)中的情況不同的。在函數(shù)中,形參和實參是
兩個不同的量,各有自己的作用域,調(diào)用時要把實參值賦予形參,進行
“值傳遞”。而在帶參數(shù)的宏中,只是符號替換,不存在值傳遞的問題;宏展開只占用編譯時間,不占用運行時間。而函數(shù)調(diào)用占用運行時間。8.1宏定義【例8-4】閱讀下面程序。#define
SV(s1,s2,s3,v)
s1=l*w;s2=l*h;s3=w*h;v=w*l*h;main(){
int
l=3,w=4,h=5,sa,sb,sc,vv;SV(sa,sb,sc,vv);printf("sa=%d\nsb=%d\nsc=%d\nvv=%d\n",sa,sb,sc,vv);6
}8.1宏定義運行結果:程序說明:第1行為宏定義,用宏名SV表示4個賦值語句,4個形參分別為4個賦值號左部的變量。在宏調(diào)用時,把4個語句宏展開并用實參替換形參,使計算結果送入實參中。8.2文件包含Code_f2文件包含是C語言預處理的另一個重要功能。文件包含命令的一般形式為:#include<文件名>功能:把指定的文件插入該命令行位置取代該命令行,從而把指定的文件和當前的源文件連成一個源文件。如圖8-3所示。f1.c
f2.c
f1.c#include<f2.c>Code_f2Code_f1+Code_f1圖8-3文件包含8.2文件包含在程序設計中,文件包含是很有用的。一個大的程序可以分為多個模塊,由多個程序員分別編程。有些公用的符號常量或宏定義等可單獨組成一個文件,在其它文件的開頭用包含命令包含該文件即可使用。這樣,可避免在每個文件開頭都去書寫那些公用量,從而節(jié)省時間,并減少出錯。對文件包含命令有以下幾點說明:(1)包含命令中的文件名可以用雙引號括起來,也可以用尖括號括起來。例如以下寫法都是允許的:#include<
stdio.h>#include"stdio.h"但是這兩種形式是有區(qū)別的:使用尖括號表示系統(tǒng)到存放C庫函數(shù)頭文件的目錄中去尋找要包含的文件,這稱為標準方式。而使用雙引號則表示首先在當前的源文件目錄中尋找,若未找到再到C庫函數(shù)頭文件8.2文件包含目錄去尋找。用戶編程時可根據(jù)自己文件所在的目錄來選擇某一種命令形式;一個include命令只能指定一個被包含文件,若有多個文件要包含,則需用多個include命令;文件包含允許嵌套,即在一個被包含的文件中又可以包含另一個文件。如圖8-4所示。f1.c
f2.c
f3.c
f1.c#include<f2.c>
#include<f3.c>Code_f1+Code_f3Code_f2圖8-4文件包含+Code_f2Code_f3Code_f18.3條件編譯8.3條件編譯條件編譯可以按不同的條件去編譯不同的程序部分,因而產(chǎn)生不同的目標代碼文件。這對于程序的移植和調(diào)試是很有用的。條件編譯有三種形式,下面分別介紹:(1)第一種形式:#if常量表達式程序段1#else程序段2#endif功能:如“常量表達式”的值為真(非0),則對“程序段1”進行編譯,否則對
“程序段2”進行編譯。因此可以使程序在不同條件下,完成不同的功能。8.3條件編譯【例8-5】閱讀下面程序。/*
條件編譯*/#define
USA
0#define
CHINA
1#define
ACTIVE_COUNTRY
CHINAvoid
main(){
char
*cur;#if
ACTIVE_COUNTRY==CHINAcur="yuan";#elsecur="dollar";#endifprintf("I
have
100
%s!",cur);}8.3條件編譯運行結果:程序說明:本例采用了#if條件編譯。在程序第3行宏定義中,定義當前國家ACTIVE_COUNTRY為CHINA,因此在條件編譯時,常量表達式的值為真,故指針變量cur指向字符串“yuan”,表示當前國家的貨幣單位是“元”。上面介紹的條件編譯當然也可以用條件語句來實現(xiàn)。但是用條件語句將會對整個源程序進行編譯,生成的目標代碼程序很長,而采用條件編譯,則根據(jù)條件只編譯其中的程序段1或程序段2,生成的目標程序較短。如果條件選擇的程序段很長,采用條件編譯的方法對于提高代碼運行效率是十分必要的。8.3條件編譯(2)第二種形式:#ifdef標識符程序段1#else程序段2#endif功能:如果“標識符”已被#define命令定義過則對“程序段1”進行編譯,否則對“程序段2”進行編譯。如果沒有“程序段2”(為空),本格式中的#else分支可以沒有,即可以寫為:#ifdef標識符程序段#endif8.3條件編譯【例8-6】閱讀下面程序。#define
NUM
1void
main(){
struct
stu{
int
num;char
*name;char
sex;float
score;8
}*ps;9
ps=(struct
stu*)malloc(sizeof(struct
stu));10
ps->num=1202;ps->name="ZhangYu";ps->sex="F";8.1宏定義13
ps->score=85.0;14
#ifdef
NUM
/*
條件編譯
*/15printf("Number=%d\nScore=%.2f\n",ps->num,ps->
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 委托印刷制作合同范例
- 刻章店合同模板
- 吊車吊裝安全合同模板
- 委托協(xié)議和合同模板
- 合作傭金合同范例
- 建安材料合同范例
- 合同范例格式 字體
- 干活合同范例
- 和超市銷售合同模板
- 建筑架施工合同范例
- GB/T 7364-1987石蠟易碳化物試驗法
- 2022年教師資格之中學教育學教育心理學全國通用試題
- 主體驗收施工單位發(fā)言稿
- 2023年聚合物材料表征測試題庫
- 碟式離心機圖片集
- 2020人文素養(yǎng)試題及答案
- 2023年四川天府銀行校園招聘筆試模擬試題及答案解析
- 鑄牢中華民族共同體意識學習PPT
- 酒店工程管理的意義
- 高血壓(英文版)-課件
- 冷庫安裝與維修4-1(冷庫的安全防護)課件
評論
0/150
提交評論