C語言程序設計_11章 預處理命令_第1頁
C語言程序設計_11章 預處理命令_第2頁
C語言程序設計_11章 預處理命令_第3頁
C語言程序設計_11章 預處理命令_第4頁
C語言程序設計_11章 預處理命令_第5頁
已閱讀5頁,還剩14頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

1、第十一章第十一章 預處理命令預處理命令概概 述述 ANSI C標準規(guī)定可以在標準規(guī)定可以在C源程序中加入一些源程序中加入一些“預處理命令預處理命令”(preprocessor directives),以改進程序設計環(huán)境,提高編程效,以改進程序設計環(huán)境,提高編程效率。這些預處理命令是由率。這些預處理命令是由ANSI C統(tǒng)一規(guī)定的,但它們統(tǒng)一規(guī)定的,但它們不是不是C語言語言本身的組成部分,更不是本身的組成部分,更不是C語句語句。編譯程序不能識別預處理命令,。編譯程序不能識別預處理命令,它們必須在對程序進行通常的它們必須在對程序進行通常的編譯(包括詞法和語法分析、代碼編譯(包括詞法和語法分析、代碼生

2、成、優(yōu)化等)生成、優(yōu)化等)之前被之前被“預處理預處理” ,即在編譯前先根據(jù)預處理命,即在編譯前先根據(jù)預處理命令的要求對程序做出相應的處理。令的要求對程序做出相應的處理。 經(jīng)過預處理后,程序不再含有預處理命令了,然后再由編譯經(jīng)過預處理后,程序不再含有預處理命令了,然后再由編譯程序對預處理后的源程序進行通常的編譯處理,得到目標代碼。程序對預處理后的源程序進行通常的編譯處理,得到目標代碼。 現(xiàn)在使用的現(xiàn)在使用的許多許多C編譯系統(tǒng)編譯系統(tǒng)都包括了都包括了預處理預處理、編譯編譯和和連接連接等部等部分,在進行編譯時一氣呵成。我們必須正確分,在進行編譯時一氣呵成。我們必須正確、,才能正確使用預處理命令。,才

3、能正確使用預處理命令。 C語言與其它高級語言的一個重要區(qū)別是可以使用預處理命令語言與其它高級語言的一個重要區(qū)別是可以使用預處理命令和具有預處理的功能。和具有預處理的功能。C語言提供的語言提供的預處理功能預處理功能主要有以下三種:主要有以下三種: 1. 宏定義宏定義 2. 文件包含文件包含 3. 條件編譯條件編譯 分別用相應的宏定義命令、文件包含命令和條件編譯命令來分別用相應的宏定義命令、文件包含命令和條件編譯命令來實現(xiàn)。為了實現(xiàn)。為了與一般與一般C語句相區(qū)別語句相區(qū)別,這些命令以,這些命令以符號符號“#”開頭開頭。11.1 11.1 宏定義宏定義11.1.1 不帶參數(shù)的宏定義不帶參數(shù)的宏定義

4、在在C語言中,我們可以定義一個指定的標識符來語言中,我們可以定義一個指定的標識符來代替代替程序程序中的一個字符串,這種定義稱為中的一個字符串,這種定義稱為“宏定義宏定義”,這個標識符(名,這個標識符(名字)稱為字)稱為“宏名宏名”。一般定義形式為:。一般定義形式為: #define 標識符標識符 字符串字符串 這就是已經(jīng)介紹過的符號常量的定義。如:這就是已經(jīng)介紹過的符號常量的定義。如: #define PI 3.1415926 它的作用是:在編譯預處理時,將程序中在該命令以后它的作用是:在編譯預處理時,將程序中在該命令以后出現(xiàn)的所有的標識符出現(xiàn)的所有的標識符PI都都替換替換為為3.141592

5、6這個這個字符串字符串。在預。在預編澤時,將宏名替換成字符串的過程稱為編澤時,將宏名替換成字符串的過程稱為“宏展開宏展開”。define是是宏定義命令宏定義命令。例例11.1#define PI 3.1415926main( ) float l,s,r,v; printf(input radius:); scanf(%f,&r); l=2.0*PI*r; s=PI*r*r; v=3.0/4*PI*r*r*r; printf(l=%10.4fns=%10.4fnv=%10.4fn,l,s,v);說明:說明:1)宏名一般宏名一般約定約定用大寫字母表示,以便與變量名相區(qū)別。用大寫字母表示,以

6、便與變量名相區(qū)別。2)使用宏定義,可以提高程序的通用性,能作到使用宏定義,可以提高程序的通用性,能作到“一改俱改一改俱改”。3)宏定義是用宏名代替一個字符串,宏定義是用宏名代替一個字符串,只作簡單的替換操作只作簡單的替換操作,不作,不作正確性檢查。如果詞義或語義錯誤,只有在編譯已被宏展開后正確性檢查。如果詞義或語義錯誤,只有在編譯已被宏展開后的源程序時才會發(fā)現(xiàn)錯誤并報錯。例如:的源程序時才會發(fā)現(xiàn)錯誤并報錯。例如: #define PI 3.14l59 把第二個把第二個“1”寫成寫成“l(fā)”。這樣的錯誤在預處理時是不會被發(fā)現(xiàn)。這樣的錯誤在預處理時是不會被發(fā)現(xiàn)的,只有在編譯時才會被發(fā)現(xiàn)井報錯。的,只

7、有在編譯時才會被發(fā)現(xiàn)井報錯。4)宏定義不是宏定義不是C語句,語句,不要隨便在行末加分號不要隨便在行末加分號。如果加了分號,。如果加了分號,則會連同分號一起進行替換。則會連同分號一起進行替換。5)#define命令出現(xiàn)在程序中函數(shù)的外面,宏名的命令出現(xiàn)在程序中函數(shù)的外面,宏名的有效范圍有效范圍為宏定為宏定義之后到本義之后到本 源文件末。通常,源文件末。通常,#define命令寫在文件開頭,函數(shù)命令寫在文件開頭,函數(shù)之前,作為文件一部分,在此文件范圍內有效。之前,作為文件一部分,在此文件范圍內有效。6)可用可用#undef 命令來終止宏定義的作用域。這樣可以靈活控制命令來終止宏定義的作用域。這樣可

8、以靈活控制宏定義的作用范圍。宏定義的作用范圍。7)在進行宏定義時,又可引用已定義的宏名,實現(xiàn)層層置換。在進行宏定義時,又可引用已定義的宏名,實現(xiàn)層層置換。8)對程序中用雙引號括起來的字符串內的字符,即使與宏名相對程序中用雙引號括起來的字符串內的字符,即使與宏名相同,也不進行置換。如下例同,也不進行置換。如下例printf 函數(shù)的格式控制串中的函數(shù)的格式控制串中的L和和S字符,它們不被置換。字符,它們不被置換。 例例9.2 #define R 3.0 #define PI 3.1415926 #define L 2*PI*R #define S PI*R*R main( ) printf(“L=

9、%fnS=%fn”,L,S); 運行結果為:運行結果為:L=18.849556S=28.274333printf(“L=%fnS=%fn”,2*3.1415926*3.0,3.1415926*3.0*3.0);11.1.2 11.1.2 帶參數(shù)的宏定義帶參數(shù)的宏定義 帶參數(shù)的宏定義也是一種替換操作,但它要進行兩次替帶參數(shù)的宏定義也是一種替換操作,但它要進行兩次替換(換(宏名字符串被簡單替換宏名字符串被簡單替換和和實參字符串簡單替換形參實參字符串簡單替換形參)。)。其定義的一般形式為:其定義的一般形式為: #define 宏名宏名(參數(shù)表參數(shù)表) 字符串字符串 字符串中包含有參數(shù)表中所指定的參數(shù)

10、。例如:字符串中包含有參數(shù)表中所指定的參數(shù)。例如: #define S(a,b) a*b area=S(2,3); 其中其中S(2,3)相當與相當與2*3 。 帶參宏定義的置換過程:帶參宏定義的置換過程: 在程序中如果有帶實參的宏在程序中如果有帶實參的宏(例如例如S(3,2),則按,則按define命令行中指定的字命令行中指定的字 符串從左到右符串從左到右進行置換;進行置換; 如果字符串中含有宏中的形參如果字符串中含有宏中的形參(如如a,b),則將,則將相應的實參字符串(可以是常量、變量或表達式)代替形參;相應的實參字符串(可以是常量、變量或表達式)代替形參; 如果字符串中的字符不是參數(shù)字符如

11、果字符串中的字符不是參數(shù)字符(如上例中如上例中*),則原樣,則原樣保留。這樣,便形成了置換的字符串。保留。這樣,便形成了置換的字符串。例例11.3#define PI 3.14#define S(r) PI*r*rmain( ) float a,area; a=3.6; area=S(a); printf(“r=%fnarea=%fn”,a,area);說明:說明:1)對帶參數(shù)的宏的展開只是將宏名后面括號內的對帶參數(shù)的宏的展開只是將宏名后面括號內的實參字符串實參字符串代替代替define命令行中的命令行中的形參形參。如果有以下語句。如果有以下語句: area=S(2+3);與與 3.14*a*

12、a 相同相同再相應的宏展開形式為:再相應的宏展開形式為:area=3.14*5*5; area=3.14*(2+3)*(2+3); area=3.14*2+3*2+3; 請注意請注意在在a+b外面沒有括弧,顯然這與程序設計者的原意不外面沒有括弧,顯然這與程序設計者的原意不符。應當在定義時,在字符串中的形式參數(shù)外面加一個括弧。符。應當在定義時,在字符串中的形式參數(shù)外面加一個括弧。即即 #define S(r) PI*(r)*(r)只有這樣才會得到:只有這樣才會得到: area=PI*(2+3)*(2+3);2)宏定義時,在宏名與帶參數(shù)的括弧之間不應加空格,否宏定義時,在宏名與帶參數(shù)的括弧之間不應

13、加空格,否則將空格以后的字符都作為宏名所代替的字符串。則將空格以后的字符都作為宏名所代替的字符串。帶參數(shù)的宏帶參數(shù)的宏和和函數(shù)函數(shù)的比較:的比較: 相似之處:在引用函數(shù)時,也是在函數(shù)名后的括弧內寫實參,也相似之處:在引用函數(shù)時,也是在函數(shù)名后的括弧內寫實參,也要求實參與形參的數(shù)目相等,但這只是表面、形式上的相似。要求實參與形參的數(shù)目相等,但這只是表面、形式上的相似。 帶參的宏定義與函數(shù)的區(qū)別:帶參的宏定義與函數(shù)的區(qū)別: 1)函數(shù)調用時,函數(shù)調用時,要先求解實參表達式的值要先求解實參表達式的值,然后代入給形參;,然后代入給形參;而使用帶參的宏,只是進行簡單的字符替換。而使用帶參的宏,只是進行簡單

14、的字符替換。2)函數(shù)調用是函數(shù)調用是在程序運行時在程序運行時處理的,要分配內存單元(棧);處理的,要分配內存單元(棧);而宏展開是而宏展開是在預處理時在預處理時進行的,在展開時并不分配內存單進行的,在展開時并不分配內存單元,不進行值的傳遞處理,更沒有元,不進行值的傳遞處理,更沒有“返回值返回值”的概念。的概念。 這是兩者最本質的區(qū)別。這是兩者最本質的區(qū)別。3)函數(shù)中的實參和形參都要定義類型,二者的類型要求函數(shù)中的實參和形參都要定義類型,二者的類型要求一致,一致,不一致,應進行類型轉換;而宏不存在類型問題,宏名無不一致,應進行類型轉換;而宏不存在類型問題,宏名無類型,它的參數(shù)也無類型,只是代表一

15、個符號。類型,它的參數(shù)也無類型,只是代表一個符號。4)每進行一次宏展開都會使源程序增長,而函數(shù)調每進行一次宏展開都會使源程序增長,而函數(shù)調 用不會。用不會。5)宏替換不占運行時間,只占預處理時間。而函數(shù)調用則要宏替換不占運行時間,只占預處理時間。而函數(shù)調用則要占運行時間(分配單元、?,F(xiàn)場、值傳遞、返回)。占運行時間(分配單元、?,F(xiàn)場、值傳遞、返回)。11.2 “11.2 “文件包含文件包含”處理處理 所謂所謂 “文件包含文件包含”處理處理是指一個源文件將另外的源文件的全是指一個源文件將另外的源文件的全部內容包含到本文件中。部內容包含到本文件中。C語言提供語言提供#include命令來實現(xiàn)命令來

16、實現(xiàn)“文件包文件包含含”的的 操作。一般形式為:操作。一般形式為: #inc1ude “文件名文件名” 或或 #include #includefile1.cABBfile2.c 常用在文件頭部的被包含文件稱為常用在文件頭部的被包含文件稱為“標題文件標題文件”或或“頭部文頭部文件件”,常以,常以“h”為后綴(為后綴(h為為head 的縮寫),如的縮寫),如“stdio.h”文件。文件。當然不用當然不用“h”為后綴,而用為后綴,而用“c”為后綴或者沒有后綴也是可以的,為后綴或者沒有后綴也是可以的,但用但用“h”作后綴更能表示此文件的性質。作后綴更能表示此文件的性質。說明:說明:1)一個一個#in

17、clude命令只能指定一個被包含文件,如果要包含命令只能指定一個被包含文件,如果要包含n個文件,個文件,要用要用n個個#include命令。命令。2)如果如果file1.c文件包含文件包含file2.h文件,而文件文件,而文件file2.h要用到要用到file3.h的內的內容,則可在容,則可在file1.c中用兩個中用兩個#include命令分別包含文件命令分別包含文件file2.h和和file3.h,而且而且file3.h應出現(xiàn)在應出現(xiàn)在file2.h之前之前。 即:即:#include “file3.h” #include “file2.h” 這樣這樣file1.c和和file2.h都可以

18、用到都可以用到file3.h的內容,的內容,并且并且file2的源文件的源文件中不用再聲明中不用再聲明#include “file3.h”。3)在一個被包含文件中又可以包含另一個被包含文件,即文件包含在一個被包含文件中又可以包含另一個被包含文件,即文件包含可以嵌套??梢郧短住?)在在#include命令中,文件名要用雙引號或尖括號括起來。命令中,文件名要用雙引號或尖括號括起來。雙引號雙引號表示編譯系統(tǒng)先在用戶當前目錄中尋找要包含的文件,若沒有,表示編譯系統(tǒng)先在用戶當前目錄中尋找要包含的文件,若沒有,則在則在C庫函數(shù)頭文件所在的目錄中尋找(庫函數(shù)頭文件所在的目錄中尋找(尖括號尖括號的含義)。的含

19、義)。5)被包含文件被包含文件(file2.h)與其所在的文件與其所在的文件(file1.c)在預處理之后已在預處理之后已成為成為同一個文件同一個文件。因此在。因此在 file2.h中若有全局靜態(tài)變量,它在中若有全局靜態(tài)變量,它在file1.c中也中也同樣有效,不必用同樣有效,不必用extern聲明。聲明。11.3 條件編譯(自學) 一般情況下,源程序中的所有行都要參加編譯。但是,一般情況下,源程序中的所有行都要參加編譯。但是,有時希望有時希望對源程序中某些內容只在滿足一定條件時才進行編對源程序中某些內容只在滿足一定條件時才進行編譯譯,這就是,這就是“條件編譯條件編譯”。 條件編譯的形式有:條

20、件編譯的形式有: (1)#ifdef 標識符標識符 程序段程序段1 #else 程序段程序段2 #endif 它的作用是當所指定的標識符已經(jīng)被它的作用是當所指定的標識符已經(jīng)被#define命令定義命令定義過,則在程序編譯階段只編譯過,則在程序編譯階段只編譯程序段程序段1,否則編譯,否則編譯程序段程序段2。 其中其中#else部分可以沒有,即部分可以沒有,即 #ifdef 標識符標識符 程序段程序段1 #endif 這里的這里的“程序段程序段”可以是語句組,也可以是命令行。可以是語句組,也可以是命令行。 這種條件編譯對于提高這種條件編譯對于提高C源程序的源程序的通用性通用性是很有好處的。是很有好

21、處的。例如:例如:如果一個如果一個C源程序要在不同的計算機系統(tǒng)上運行,而源程序要在不同的計算機系統(tǒng)上運行,而不同的計算機系統(tǒng)又存在一定的差異(例如,有的機器以不同的計算機系統(tǒng)又存在一定的差異(例如,有的機器以16位來存放一個整數(shù),而有的則以位來存放一個整數(shù),而有的則以32位存放一個整數(shù)),這樣位存放一個整數(shù)),這樣往往需要對源程序作必要的修改,這就降低了程序的通用性,往往需要對源程序作必要的修改,這就降低了程序的通用性,可以用以下的條件編譯來處理。可以用以下的條件編譯來處理。 #ifdef COMPUTER_A #define INTEGER_SIZE 16 #else #define INT

22、EGER_SIZE 32 #endif 如果如果COMPUTER_A在前面已被定義過,則編譯下面的在前面已被定義過,則編譯下面的命令行:命令行: #define INTEGER_SIZE 16否則,編譯下面的命令行否則,編譯下面的命令行: #define INTEGER_SIZE 32如果在這組條件編譯命令之前曾出現(xiàn)以下命令行:如果在這組條件編譯命令之前曾出現(xiàn)以下命令行: #define COMPUTER_A 0或將或將COMPUTER_A定義為任何字符串,甚至是定義為任何字符串,甚至是: #define COMPUTER_A則預處理后程序中的則預處理后程序中的INTEGER_SIZE都用都用

23、16代替,否則都代替,否則都用用32代替。代替。 這樣,源程序可以不必作任何修改就可以用于不同類型這樣,源程序可以不必作任何修改就可以用于不同類型的計算機系統(tǒng)。的計算機系統(tǒng)。又如:又如:在程序調試時,常常希望輸出一些所需的信息,而在程序調試時,常常希望輸出一些所需的信息,而在調試完成后不再輸出這些信息??梢栽谠闯绦蛑胁迦胍栽谡{試完成后不再輸出這些信息??梢栽谠闯绦蛑胁迦胍韵碌臈l件編譯段。下的條件編譯段。 #ifdef DEBUG printf(“x=%d,y=%d,z=%dn”,x,y,z); #endif如果在它的前面有以下命令行:如果在它的前面有以下命令行: #define DEBUG 則在程序運行時輸出則在程序運行時輸出x, y, z 的值,

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論