C語言條件編譯及編譯預(yù)處理階段_第1頁
C語言條件編譯及編譯預(yù)處理階段_第2頁
C語言條件編譯及編譯預(yù)處理階段_第3頁
C語言條件編譯及編譯預(yù)處理階段_第4頁
C語言條件編譯及編譯預(yù)處理階段_第5頁
已閱讀5頁,還剩5頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

1、C語言條件編譯及編譯預(yù)處理階段一、C語言由源代碼生成的各階段如下:C源程序>編譯預(yù)處理>編譯>優(yōu)化程序>匯編程序>鏈接程序>可執(zhí)行文件其中 編譯預(yù)處理階段,讀取c源程序,對其中的偽指令(以#開頭的指令)和特殊符號進(jìn)行處理?;蛘哒f是掃描源代碼,對其進(jìn)行初步的轉(zhuǎn)換,產(chǎn)生新的源代碼提供給編譯器。預(yù)處理過程先于編譯器對源代碼進(jìn)行處理。在C 語言中,并沒有任何內(nèi)在的機(jī)制來完成如下一些功能:在編譯時包含其他源文件、定義宏、根據(jù)條件決定編譯時是否包含某些代碼。要完成這些工作,就需要使用預(yù)處理程序。盡管在目前絕大多數(shù)編譯器都包含了預(yù)處理程序,但通常認(rèn)為它們是獨(dú)立于編譯器的。

2、預(yù)處理過程讀入源代碼,檢查包含預(yù)處理指令的語句和宏定義,并對源代碼進(jìn)行響應(yīng)的轉(zhuǎn)換。預(yù)處理過程還會刪除程序中的注釋和多余的空白字符。二、偽指令(或預(yù)處理指令)定義預(yù)處理指令是以#號開頭的代碼行。#號必須是該行除了任何空白字符外的第一個字符。#后是指令關(guān)鍵字,在關(guān)鍵字和#號之間允許存在任意個數(shù)的空白字符。整行語句構(gòu)成了一條預(yù)處理指令,該指令將在編譯器進(jìn)行編譯之前對源代碼做某些轉(zhuǎn)換。下面是部分預(yù)處理指令: 指令用途#空指令,無任何效果#include包含一個源代碼文件#define定義宏#undef取消已定義的宏#if如果給定條件為真,則編譯下面代碼#ifdef如果宏已經(jīng)定義,則編譯下面代碼#ifn

3、def如果宏沒有定義,則編譯下面代碼#elif如果前面的#if給定條件不為真,當(dāng)前條件為真,則編譯下面代碼,其實(shí)就是elseif的簡寫#endif結(jié)束一個#if#else條件編譯塊#error停止編譯并顯示錯誤信息三、預(yù)處理指令主要包括以下四個方面:1、宏定義指令宏定義了一個代表特定內(nèi)容的標(biāo)識符。預(yù)處理過程會把源代碼中出現(xiàn)的宏標(biāo)識符替換成宏定義時的值。宏最常見的用法是定義代表某個值的全局符號。宏的第二種用 法是定義帶參數(shù)的宏(宏函數(shù)),這樣的宏可以象函數(shù)一樣被調(diào)用,但它是在調(diào)用語句處展開宏,并用調(diào)用時的實(shí)際參數(shù)來代替定義中的形式參數(shù)。/例1#define MAX_NUM 10int array

4、MAX_NUM;for(i=0;i 在這個例子中,對于閱讀該程序的人來說,符號MAX_NUM就有特定的含義,它代表的值給出了數(shù)組所能容納的最大元素?cái)?shù)目。程序中可以多次使用這個值。作為一種約定,習(xí)慣上總是全部用大寫字母來定義宏,這樣易于把程序的宏標(biāo)識符和一般變量標(biāo)識符區(qū)別開來。如果想要改變數(shù)組的大小,只需要更改宏定義并重新編譯程序即可。一是使用方便。如下:/例2#define PAI 3.1415926PAI顯然比3.1415926寫著方便。二是定義的宏有了意義,可讀性強(qiáng)。如例1,MAX_NUM,望文生意便知是最大數(shù)量的意思,比單純使用10這個數(shù)字可讀性要強(qiáng)的多。三是容易修改。如例1,如果在程序

5、中有幾十次會使用到MAX_NUM,修改只需要在宏定義里面修改一次就可以,否則你會修改到崩潰。/例3#define ONE 1#define TWO 2#define SUM(ONE+TWO這里需要注意兩點(diǎn):一是注意上面的宏定義使用了括號。盡管它們并不是必須的。但出于謹(jǐn)慎考慮,還是應(yīng)該加上括號的。例如:six=THREE*TWO;預(yù)處理過程把上面的一行代碼轉(zhuǎn)換成:six=(ONE+TWO*TWO;如果沒有那個括號,就轉(zhuǎn)換成:six=ONE+TWO*TWO;了。也就是說預(yù)處理僅是簡單的字符替換,要時刻注意這一點(diǎn),很多錯誤都會因此出現(xiàn)。二是雖然我們舉例用了#define ONE 1 這個例子,但是一

6、般要求宏定義要有其實(shí)際意義,#define ONE 1這種沒意義的宏定義是不推薦的。(大概是這么個意思,忘記具體怎么說了)#define VERSION "Version 1.0 Copyright(c 2003"1.2 帶參數(shù)的#define指令(宏函數(shù))帶參數(shù)的宏和函數(shù)調(diào)用看起來有些相似??匆粋€例子:/例4#define Cube(x (x*(x*(x可以時任何數(shù)字表達(dá)式甚至函數(shù)調(diào)用來代替參數(shù)x。這里再次提醒大家注意括號的使用。宏展開后完全包含在一對括號中,而且參數(shù)也包含在括號中,這樣就保證了宏和參數(shù)的完整性??匆粋€用法:/例4用法int num=8+2;volume=

7、Cube(num;展開后為(8+2*(8+2*(8+2;如果沒有那些括號就變?yōu)?+2*8+2*8+2了(切記。下面的用法是不安全的:volume=Cube(num+;如果Cube是一個函數(shù),上面的寫法是可以理解的。但是,因?yàn)镃ube是一個宏,所以會產(chǎn)生副作用。這里的書寫不是簡單的表達(dá)式,它們將產(chǎn)生意想不到的結(jié)果。它們展開后是這樣的:volume=(num+*(num+*(num+;很顯然,結(jié)果是10*11*12,而不是10*10*10;那么怎樣安全的使用Cube宏呢?必須把可能產(chǎn)生副作用的操作移到宏調(diào)用的外面進(jìn)行:int num=8+2;volume=Cube(num;num+;宏函數(shù)使用不當(dāng)

8、會出現(xiàn)一些難以發(fā)現(xiàn)的錯誤,請慎重使用。1.3 #運(yùn)算符出現(xiàn)在宏定義中的#運(yùn)算符把跟在其后的參數(shù)轉(zhuǎn)換成一個字符串。有時把這種用法的#稱為字符串化運(yùn)算符。例如:/例5#define PASTE(n "adhfkj"#nint main(printf("%sn",PASTE(15;return 0;/輸出adhfj15宏定義中的#運(yùn)算符告訴預(yù)處理程序,把源代碼中任何傳遞給該宏的參數(shù)轉(zhuǎn)換成一個字符串。所以輸出應(yīng)該是:adhfkj15。1.4 #運(yùn)算符(很少用)#運(yùn)算符用于把參數(shù)連接到一起。預(yù)處理程序把出現(xiàn)在#兩側(cè)的參數(shù)合并成一個符號??聪旅娴睦樱?例6#def

9、ine NUM(a,b,c a#b#c#define STR(a,b,c a#b#cint main(printf("%dn",NUM(1,2,3;printf("%sn",STR("aa","bb","cc"return 0;/最后程序的輸出為:123aabbcc2、條件編譯指令。程序員可以通過定義不同的宏來決定編譯程序?qū)δ男┐a進(jìn)行處理。條件編譯指令將決定那些代碼被編譯,而哪些是不被編譯的??梢愿鶕?jù)表達(dá)式的值或者某個特定的宏是否被定義來確定編譯條件。(條件編譯為了提高程序的可移植性,增加程序

10、的靈活性。便于程序在不同的軟硬件環(huán)境下都可正常運(yùn)行而不需要修改程序。比如說一個商業(yè)軟件,面向的是不同的硬件系統(tǒng)和軟件系統(tǒng),如果移植性不好,那賣出去的軟件在每個環(huán)境下都要單獨(dú)設(shè)置,那軟件公司的開發(fā)人員每天都要做這樣的修改程序的工作,會影響正常的工作。所以對需要的部分進(jìn)行條件編譯,可以大大降低軟件需要改動的部分或者不改動。舉個例子,你如果將一個函數(shù)聲明2次,編譯器就會報(bào)錯。所以把函數(shù)聲明寫在頭文件中后,如果引用了2次這個頭文件,也會報(bào)錯。#ifndef #define 宏就是用來避免頭文件重復(fù)包含的,意思是 如果沒有這個定義,就定義下面的內(nèi)容。條件編譯是為了代碼能在不同的環(huán)境中都編譯通過,通用性更

11、好。)2.1 #if/#endif/#else/#elif指令#if指令檢測跟在制造另關(guān)鍵字后的常量表達(dá)式。如果表達(dá)式為真,則編譯后面的代碼,直到出現(xiàn)#else、#elif或#endif為止;否則就不編譯。#endif用于終止#if預(yù)處理指令。#else指令用于某個#if指令之后,當(dāng)前面的#if指令的條件不為真時,就編譯#else后面的代碼。/例7#define DEBUG /此時#ifdef DEBUG為真/#define DEBUG 0 /此時為假int main(#ifdef DEBUGprintf("Debuggingn"#elseprintf("Not

12、debuggingn"#endifprintf("Runningn"return 0;這樣我們就可以實(shí)現(xiàn)debug功能,每次要輸出調(diào)試信息前,只需要#ifdef DEBUG判斷一次。不需要了就在文件開始定義#define DEBUG 0#elif預(yù)處理指令綜合了#else和#if指令的作用。/例8#define TWOint main(#ifdef ONEprintf("1n"#elif defined TWOprintf("2n"#elseprintf("3n"#endif/輸出結(jié)果是2。2.2 #if

13、def和#ifndef這二者主要用于防止重復(fù)包含。我們一般在.h頭文件前面加上這么一段:/頭文件防止重復(fù)包含/funcA.h#ifndef FUNCA_H#define FUNCA_H/頭文件內(nèi)容#end if3、頭文件包含指令。采用頭文件的目的主要是為了使某些定義可以供多個不同的C源程序使用。因?yàn)樵谛枰玫竭@些定義的C源程序中,只需加上一條#include語句即可,而不必再在此文件中將這些定義重復(fù)一遍。預(yù)編譯程序?qū)杨^文件中的定義統(tǒng)統(tǒng)都加入到它所產(chǎn)生的輸出文件中,以供編譯程序?qū)χM(jìn)行處理。#include預(yù)處理指令的作用是在指令處展開被包含的文件。包含可以是多重的,也就是說一個被包含的文件中

14、還可以包含其他文件。標(biāo)準(zhǔn)C編譯器至少支持 八重嵌套包含。預(yù)處理過程不檢查在轉(zhuǎn)換單元中是否已經(jīng)包含了某個文件并阻止對它的多次包含,這個的處理辦法上面已經(jīng)給出。在程序中包含頭文件有兩種格式:#include #include "my.h"第一種方法是用尖括號把頭文件括起來。這種格式告訴預(yù)處理程序在編譯器自帶的或外部庫的頭文件中搜索被包含的頭文件。第二種方法是用雙引號把頭文件括起來。這種格式告訴預(yù)處理程序在當(dāng)前被編譯的應(yīng)用程序的源代碼文件中搜索被包含的頭文件,如果找不到,再搜索編譯器自帶的頭文件。采用兩種不同包含格式的理由在于,編譯器是安裝在公共子目錄下的,而被編譯的應(yīng)用程序是在

15、它們自己的私有子目錄下的。一個應(yīng)用程序既包含編譯器提供的公共頭文件,也包含自定義的私有頭文件。采用兩種不同的包含格式使得編譯器能夠在很多頭文件中區(qū)別出一組公共的頭文件。4、特殊符號。預(yù)編譯程序可以識別一些特殊的符號。預(yù)編譯程序?qū)τ谠谠闯绦蛑谐霈F(xiàn)的這些串將用合適的值進(jìn)行替換。4.1 _LINE_注意,是雙下劃線,而不是單下劃線 。_FILE_ 包含當(dāng)前程序文件名的字符串_LINE_ 表示當(dāng)前行號的整數(shù)_DATE_ 包含當(dāng)前日期的字符串_STDC_ 如果編譯器遵循ANSI C標(biāo)準(zhǔn),它就是個非零值_TIME_ 包含當(dāng)前時間的字符串/例9#include int main(printf("Hello World!n"printf("%sn",_FILE_;printf("%dn",_LINE_;return 0;4.2 #line等#error指令將使編譯器顯示一條錯誤信息,然后停止編譯。#line指令改變_LINE_與_FILE_的內(nèi)容,它們是在編譯程序中預(yù)先定義的標(biāo)識符。#pragma指令沒有正式的定義。編譯器可以自定義其用途。典型的用法是禁止或允許某些煩人的警告信息。/例10,#line舉例#line 100 /初始化行計(jì)數(shù)器 #include /行號10

溫馨提示

  • 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

提交評論