版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
1、第第9章章 編譯預(yù)處理編譯預(yù)處理第第9章章 編譯預(yù)處理編譯預(yù)處理9.1 宏定義宏定義9.2 文件包含文件包含9.3 條件編譯條件編譯習(xí)題習(xí)題9第第9章章 編譯預(yù)處理編譯預(yù)處理9.1 宏定義宏定義 9.1.1 無參數(shù)的宏定義 無參數(shù)宏的宏名后不帶參數(shù)。其定義的一般格式為#define 宏名 字符串 其中的“#”表示這是一條預(yù)處理命令。凡是以“#”開頭的均為預(yù)處理命令。“define”為宏定義命令?!昂昝睘樗x的宏名?!白址笨梢允浅?shù)、表達式和格式串等。在前面介紹過的符號常量的定義就是一種無參宏定義。此外,常對程序中反復(fù)使用的表達式進行宏定義。第第9章章 編譯預(yù)處理編譯預(yù)處理1. 無參數(shù)宏
2、定義符號常量 符號常量用無參數(shù)的宏定義語句定義,把符號常量名定義為指定的字符串,將程序中出現(xiàn)宏名的地方均用該字符串來替換。在進行編譯預(yù)處理時,用該字符串替代程序中出現(xiàn)的符號常量名。例如:#define TRUE 1#define FALSE 0把TRUE定義為1,把FALSE定義為0。在符號常量定義之后,就可以用它來編碼了。 第第9章章 編譯預(yù)處理編譯預(yù)處理例如:if(i=TRUE) printf(you are right! n) ;else if(i=FALSE) printf(you are wrong! n) ;對于該程序段,在進行編譯預(yù)處理時,就把程序中出現(xiàn)的TRUE和FALSE分別
3、用1和0替代,于是就變?yōu)閕f(i=1) printf(you are right! n) ;else if(i=0) printf(you are wrong! n) ;第第9章章 編譯預(yù)處理編譯預(yù)處理在符號常量定義語句中,字符串可以是一個數(shù)值型數(shù)據(jù)、表達式或字符串。例如:#define PI 3.1415926#define S (PI*r*r)#define PRT printf#define A (20-(3*4) 如果字符串是一個運算表達式,一般應(yīng)該用括號括住它,以便把它視為一個操作對象與其他操作數(shù)進行運算,否則,會由于操作優(yōu)先級問題而發(fā)生錯誤。例如:text = A*8 ;進行編譯預(yù)
4、處理后,該表達式變?yōu)閠ext = (20-(3*4)*8 ;第第9章章 編譯預(yù)處理編譯預(yù)處理如果A定義為#define A 20- (3*4)則表達式text = A*8經(jīng)預(yù)編譯后變?yōu)閠ext = 20- (3*4)*8 ;這就不符合原意。因此,在宏定義語句中的字符串為一般表達式(而不是一個操作數(shù))時,為了保證正確的運算次序,應(yīng)該用括號括住它。因此在宏定義時必須十分注意,應(yīng)保證在宏代換之后不發(fā)生錯誤。第第9章章 編譯預(yù)處理編譯預(yù)處理2. 無參數(shù)宏的好處 在程序設(shè)計中,使用無參數(shù)的宏有下面兩點好處:1) 增強程序的可讀性 以符號常量為例,由于符號常量含義明確,于是采用符號常量書寫的程序要比不采用
5、符號常量的可讀性強。例如:#define LENGTH 20#define WIDTH 40#define HEIGTH 60在程序中用LENGTH、WIDTH、HEIGTH時,一看就知道它們分別代表長、寬、高,而如果直接用20、40、60,則很難猜出它們是長、寬、高。第第9章章 編譯預(yù)處理編譯預(yù)處理2) 增強程序的可維護性 如果一個常量在程序中多次被引用,則可把它定義為符號常量。這樣,在以后需改動該常量時,只需改動它的宏定義語句即可,而不必對每一個引用它的地方進行修改。這不但可以減少修改的工作量,而且可以避免漏改。3. 無參數(shù)宏的注意事項 使用無參數(shù)宏定義符號常量時,一般應(yīng)注意以下幾點。 (
6、1) 宏定義是用宏名來表示一個字符串,在宏展開時又以該字符串取代宏名,這只是一種簡單的代換,字符串中可以含任何字符,可以是常數(shù),也可以是表達式,預(yù)處理程序?qū)λ蛔魅魏螜z查。如有錯誤,則只能在編譯已被宏展開后的源程序時發(fā)現(xiàn)。第第9章章 編譯預(yù)處理編譯預(yù)處理(2) 符號常量名一般用大寫字母(也可以用小寫字母)表示,以便與其他標識符相區(qū)別。符號常量名的命名規(guī)則與一般標識符相同。另外,應(yīng)考慮在字符串中根據(jù)需要加上括號。 (3) 宏定義不是說明或語句,因此,不能用分號結(jié)尾。如果加上分號,則分號被作為字符串的一部分,連分號也一起置換。例如:#define A 60 ; 上面的格式表示A被定義為“60 ;”
7、,而不是“60”。于是,在預(yù)編譯時,程序中凡是出現(xiàn)A的地方,都用“60 ;”替換。這就不符合原意了。 (4) 替換字符串可以為空。第第9章章 編譯預(yù)處理編譯預(yù)處理(5) 宏定義語句應(yīng)放在函數(shù)定義之外,符號常量的有效范圍是從定義它的宏定義語句開始至所在源文件的結(jié)尾。一般宏定義語句都放在源文件的開頭,以便使它對整個源文件都有效。(6) 為了靈活控制宏定義的作用范圍,可用“undef”命令終止宏定義的作用域。第第9章章 編譯預(yù)處理編譯預(yù)處理例如:#define PI 3.14159main( ) # undef PI /* PI的宏定義結(jié)束 */f1( ) 表示PI只在main函數(shù)中有效,在f1中無
8、效。 第第9章章 編譯預(yù)處理編譯預(yù)處理 (7) 宏定義允許嵌套,在宏定義的字符串中可以使用已經(jīng)定義的宏名。在宏展開時由預(yù)處理程序?qū)訉哟鷵Q。例如:#define PI 3.14 #define R 10 #define S PI*R*Rmain( ) printf(S=%f , S);預(yù)編譯后,該程序變?yōu)閙ain( ) printf(S=%f , 3.14*10*10);第第9章章 編譯預(yù)處理編譯預(yù)處理(8) 宏名在源程序中若用引號括起來,則預(yù)處理程序不對其作宏代換。例如:#define NO 220main( ) printf(NO); printf(n);上例中定義宏名NO表示220,但在p
9、rintf語句中NO被引號括起來,因此不作宏代換。程序的運行結(jié)果為NO表示把“NO”當字符串處理。第第9章章 編譯預(yù)處理編譯預(yù)處理 【例9-1】假設(shè)血壓正常值低壓為70,高壓為120。如果低壓高于70,并且高壓低于120,則為正常。從鍵盤輸入血壓值,判斷該血壓值是否正常。#include main( )#define LOW 70/* 定義宏 */#define HIGH 120/* 定義宏 */第第9章章 編譯預(yù)處理編譯預(yù)處理 int bloodplow , bloodphigh ; do scanf(%d%d , &bloodphigh , &bloodplow) ; while(bloo
10、dplow=bloodphigh) ; if(bloodplowLOW & bloodphighHIGH) printf(you are right!) ; else printf(you may have something wrong!) ; 輸入:130 80 輸出:you may have something wrong!第第9章章 編譯預(yù)處理編譯預(yù)處理 【例9-2】已知一梯形的上下兩邊的長分別為a、b,輸入高h,求其面積。#include main( )#define a 5/* 定義宏 */#define b 15/* 定義宏 */#define L (a+b)/* 嵌套定義宏 *
11、/第第9章章 編譯預(yù)處理編譯預(yù)處理 float h , s ; scanf(%f , &h) ; s=h*L/2 ; printf(s=%f n , s) ; 輸入:3 輸出:s=30.000000第第9章章 編譯預(yù)處理編譯預(yù)處理【例9-3】利用迭代法求方程的根。其迭代公式為yi+1=(yi+x/yi)/2。#include stdio.hmain( )#define ABS 1e-4 float y1 , y , x ; printf(x=) ; scanf(%f ,& x) ; printf(y=) ; scanf(%f , &y) ; do第第9章章 編譯預(yù)處理編譯預(yù)處理 y1=y ;
12、y=(y1+x/y1)/2 ; while(y1-y)ABS) ; printf(%fn , y) ; 運行結(jié)果:x=2y=31.414214第第9章章 編譯預(yù)處理編譯預(yù)處理9.1.2 帶參數(shù)的宏定義1. 帶參數(shù)的宏的定義 利用#define語句不僅可以定義符號常量,也可以定義帶參數(shù)的宏。帶參數(shù)的宏的一般定義格式為#define 宏名(參數(shù)表) 字符串字符串中包含參數(shù)表中的參數(shù)。 調(diào)用帶參數(shù)宏的一般格式為宏名(實參表); 例如:#define MIN(a,b) (a)(b)? (a) : (b)第第9章章 編譯預(yù)處理編譯預(yù)處理其中,MIN(a,b)是帶參數(shù)的宏,a和b是形式參數(shù)。該定義把MIN
13、(a,b)定義為“(a)(b)? (a):(b)”。在定義了該宏后,就可在程序中用MIN(a,b)替代定義它的運算表達式“(a)(b)? (a):(b)”。宏的使用方法類似函數(shù)。例如,在需要求兩個數(shù)的最小值時,就可以使用已定義的宏。c= MIN(10,20) ; 在進行編譯時,預(yù)編譯程序根據(jù)宏定義式來替換程序中出現(xiàn)的帶參數(shù)的宏,其中定義式中的形式參數(shù)用相應(yīng)的實際參數(shù)替換。于是,上面的賦值語句變?yōu)閏= MIN(10=0)? (x): -(x)/* 求x的絕對值 */#define MAX(a,b) (a)b)?a:b改寫為 #define MAX(a,b) (ab)?a:b將被認為是無參宏定義,
14、宏名MAX代表字符串“(a,b) (ab)?a:b”。宏展開時,宏調(diào)用語句:max=MAX(x,y);將變?yōu)?max=(a,b)(ab)?a:b(x,y);這顯然是錯誤的。第第9章章 編譯預(yù)處理編譯預(yù)處理【例9-4】鍵盤輸入立方體的邊長a,求其表面積s及體積v。#include main( )#define L(a,s,v) s=6*a*a ; v=a*a*a int a1,s1,v1; a1=0 ; scanf(%d,&a1) ; L(a1,s1,v1) ; printf(%d , %d , %dn , a1 , s1 , v1) ;第第9章章 編譯預(yù)處理編譯預(yù)處理【例9-5】求1100所有
15、奇數(shù)的和。#include main( )#define ISODD(x) (x)%2=1)? 1:0) int sum , i ; sum=1 ; for(i=3 ; i=100 ; i+) if ISODD(i) sum+=i ; printf(%dn , sum) ;第第9章章 編譯預(yù)處理編譯預(yù)處理【例9-6】已知某單位上繳個人所得稅的算法如下:輸入工資,求其應(yīng)上繳的稅款。#include main( )#define TAX1(a) (a=800) ? 0 : (a1300)? 0.05 : (a=2800) ? 0.1 : (a=5800) ? 0.15 : 0.2)#define
16、TAX2(b) (b=1300) ? 0 : (b=2800)? 25 : (b=5800)? 125 : 375)#define TAX3(c) c*TAX1(c)-TAX2(c)第第9章章 編譯預(yù)處理編譯預(yù)處理 float tax , wage ; scanf(%f , &wage) ; tax=TAX3(wage) ; printf(%f , %fn , wage , tax) ;第第9章章 編譯預(yù)處理編譯預(yù)處理【例9-7】輸入4個整數(shù),按由小到大的順序輸出。#include main( )#define CHANGE(a,b) int t ; t=a; a=b; b=t ; int i
17、 , j , k , l ; printf(please input four number:) ; scanf(%d , %d , %d , %d , &i , &j , &k , &l) ;第第9章章 編譯預(yù)處理編譯預(yù)處理if(ij) CHANGE(i , j) ; if(ik) CHANGE (i , k) ; if(il) CHANGE (i , l) ; if(jk) CHANGE (j , k) ; if(jl) CHANGE (j , l) ; if(kl) CHANGE (k , l) ; printf(the proper order is:) ; printf(%d %d
18、%d %dn , i , j , k , l) ;第第9章章 編譯預(yù)處理編譯預(yù)處理9.2 文件包含文件包含在前面章節(jié)中,我們經(jīng)常在編寫程序中,會寫上下面的語句:#include 其含義是在編譯時,用stdio.h頭文件的內(nèi)容替換該語句。 文件包含語句的一般格式為#include 文件名或 #include 第第9章章 編譯預(yù)處理編譯預(yù)處理其中,是被包含文件的文件名,它是一個磁盤文件。該預(yù)編譯語句的功能是要將所指文件的全部內(nèi)容包含在該#include語句所在的源文件中。也就是說,在預(yù)編譯時,用所指文件的全部內(nèi)容替換該#include語句行,使該文件成為這個源文件的一部分。 在#include語句
19、的書寫格式中,被包含文件的文件名可用尖括號()括住,也可以用雙引號( )括住。 當用尖括號括住時,表示編譯系統(tǒng)按系統(tǒng)設(shè)定的標準目錄搜索文件;當用雙引號括住時,表示按指定的路徑搜索。若未指定路徑名時,則在當前目錄中搜索。第第9章章 編譯預(yù)處理編譯預(yù)處理文件包含語句是很有用的語句,特別是對包括多個源文件的大程序來說,可以把各個源文件中共同使用的函數(shù)說明、符號常量定義、外部量說明、宏定義和結(jié)構(gòu)類型定義等寫成一個獨立的包含文件,在需要這些說明的源文件中,只需在源文件的開頭用一個#include語句把該文件包括進來,這樣就可以避免重復(fù)工作。例如:/* file1.c */#include file2.h
20、main( ) /*file2.h*/#define PI 3.14159第第9章章 編譯預(yù)處理編譯預(yù)處理 做成包含文件的另一個好處是,當這些常量、宏定義等需要修改時,只需修改這個被包含的文件即可,而不必修改各源文件。 使用#include語句時,應(yīng)注意以下兩點: (1) 一個include命令只能指定一個被包含文件,若有多個文件要包含,則需用多個include命令。 (2) 文件包含允許嵌套,即在一個被包含的文件中又可以包含另一個文件。第第9章章 編譯預(yù)處理編譯預(yù)處理9.3 條件編譯條件編譯一般情況下,源程序中所有的行都參加編譯,但有時在寫程序時要求根據(jù)具體情況編譯不同的程序代碼,C語言中提
21、供了條件編譯,可以按不同的條件去編譯不同的程序部分,因而產(chǎn)生不同的目標代碼文件。這對于程序的移植和調(diào)試是很有用的。條件編譯有3種形式,下面分別介紹。第第9章章 編譯預(yù)處理編譯預(yù)處理1. #ifdef #else #endif語句 用# ifdef # else # endif語句進行條件編譯的指令格式為#ifdef 標識符 程序段1#else 程序段2#endif其作用是:如果標識符已被定義(用#define定義),則對程序段1進行編譯,而程序段2被刪除;否則,程序段1被刪除,編譯程序段2。其中,#else部分是可以缺省的,即第第9章章 編譯預(yù)處理編譯預(yù)處理#ifdef 標識符 程序段1#en
22、dif 條件編譯語句中的#ifdef和#endif決定了編譯范圍,在此范圍外的源程序不存在條件編譯問題。條件編譯對于提高程序的移植性很有幫助。第第9章章 編譯預(yù)處理編譯預(yù)處理【例9-8】條件編譯#ifdef的使用。#include stdio.h#define TED 10main ( ) #ifdef TED printf(Hi Tedn); /* 如果定義了TED,則編譯此行代碼 */ #else printf(Hi anyonen); /* 如果沒用定義TED,則編譯此行代碼 */第第9章章 編譯預(yù)處理編譯預(yù)處理printf(Hi anyonen); /* 如果沒用定義TED,則編譯此行
23、代碼 */ #endif #ifndef RALPH printf (RALPH not definedn); /* 如果定義了RALPH,則編譯此行代碼 */ #endif 上述代碼打印“Hi Ted”及“RALPH not defined”。如果TED沒有定義,則顯示“Hi anyone”,后面是“RALPH not defined”。可以像嵌套#if 那樣將#ifdef 與# ifndef 嵌套至任意深度。第第9章章 編譯預(yù)處理編譯預(yù)處理2. #ifndef #else #endif語句 由#ifndef #else #endif語句進行條件編譯的指令格式為#ifndef 標識符 程序段
24、1#else 程序段2#endif與第一種形式的區(qū)別是將“ifdef”改為“ifndef”。它的功能是:如果標識符未被#define命令定義,則對程序段1進行編譯,否則對程序段2進行編譯。這與第一種形式的功能正相反。例如:第第9章章 編譯預(yù)處理編譯預(yù)處理#ifndef UNPRN printf(Name= %s sa= %f, name , s) ; #else printf(%s %f , name , s) ; #endif當UNPRN在程序段之前未定義時,則只編譯“printf(Name= %s sa= %f, name , s) ;”。如果在該程序段之前加一行:#define UNPR
25、N 1則只編譯“printf(%s %f , name , s) ;”。其中,UNPRN可定義為任何字符串。第第9章章 編譯預(yù)處理編譯預(yù)處理3. #if #else #endif語句 由#if # else # endif語句進行條件編譯的指令格式為#if 表達式 程序段1#else 程序段2#endif其作用是:當表達式的值為非0時,編譯程序段1,不編譯程序段2;否則編譯程序段2(其中#else部分是可以缺省的)。例如,在程序設(shè)計的測試階段,經(jīng)常要顯示一些變量的信息,以檢查是否正確,而在正式執(zhí)行時,卻不需要顯示這些信息。這時,就可以用下面形式的條件編譯。 第第9章章 編譯預(yù)處理編譯預(yù)處理#d
26、efine DEBUG 1#if DEBUG printf(a=%d b=%f c=%s , a , b , c) ; #endif以上形式的條件編譯適用測試階段,如果程序測試完成,在編譯正式的執(zhí)行代碼時,只需把DEBUG定義為0即可。在進行條件編譯時,可根據(jù)情況選擇條件編譯語句。第第9章章 編譯預(yù)處理編譯預(yù)處理【例9-9】條件編譯#if的使用。#include stdio.h#define R 1main( ) float c,r,s; printf (input a number: ); scanf(%f,&c); #if R第第9章章 編譯預(yù)處理編譯預(yù)處理r=3.14159*c*c; /* 如果R非0,則編譯此行和下一行代碼 */ printf(area of round is: %fn,r); #else s=c*c; /* 如果R為0,則編譯此行和下一行代碼 */ printf(area of square is: %fn,s); #endif第第9章章 編譯預(yù)處理編
溫馨提示
- 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)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 中醫(yī)飲食護理在疾病康復(fù)中的作用
- 信息安全管理要點探討
- 2026年高級會計實務(wù)操作技能測試題
- 2026年電子商務(wù)運營高級經(jīng)理考試題集及答案
- 2026年計算機網(wǎng)絡(luò)安全網(wǎng)絡(luò)攻擊與防御策略題集
- 2026年網(wǎng)絡(luò)安全工程師認證題庫網(wǎng)絡(luò)安全協(xié)議解析202X年度考試題集
- 2026年化學(xué)實驗室安全操作標準化模擬考試
- 2026年營銷策略市場分析與消費者行為試題
- 2026年企業(yè)文化與團隊建設(shè)基礎(chǔ)試題
- 2026年金融風(fēng)險管理與防控測試題庫
- 養(yǎng)老院電氣火災(zāi)培訓(xùn)課件
- 對外話語體系構(gòu)建的敘事話語建構(gòu)課題申報書
- 馬年猜猜樂(馬的成語)打印版
- 精神障礙防治責(zé)任承諾書(3篇)
- 2025年擔(dān)保公司考試題庫(含答案)
- 2025年金融控股公司行業(yè)分析報告及未來發(fā)展趨勢預(yù)測
- 質(zhì)量控制計劃模板全行業(yè)適用
- 實施指南(2025)《HG-T3187-2012矩形塊孔式石墨換熱器》
- 人教版PEP五年級英語下冊單詞表與單詞字帖 手寫體可打印
- 家具制造廠家授權(quán)委托書
- 中日友好醫(yī)院公開招聘工作人員3人筆試參考題庫(共500題)答案詳解版
評論
0/150
提交評論