資源描述:
《c語(yǔ)言頭文件的建立與使用.pdf》由會(huì)員上傳分享,免費(fèi)在線閱讀,更多相關(guān)內(nèi)容在教育資源-天天文庫(kù)。
1、嵌入式c語(yǔ)言頭文件的建立與使用如何正確編寫C語(yǔ)言頭文件和與之相關(guān)聯(lián)的c源程序文件,這首先就要了解它們的各自功能。要理解C文件與頭文件(即.h)有什么不同之處,首先需要弄明白編譯器的工作過程。一般說來(lái)編譯器會(huì)做以下幾個(gè)過程:1.預(yù)處理階段2.編譯階段,首先編譯成純匯編語(yǔ)句,再將之匯編成跟CPU相關(guān)的二進(jìn)制碼,生成各個(gè)目標(biāo)文件(.obj文件)3.連接階段,將各個(gè)目標(biāo)文件中的各段代碼進(jìn)行絕對(duì)地址定位,生成跟特定平臺(tái)相關(guān)的可執(zhí)行文件。編譯器在編譯時(shí)是以C文件為單位進(jìn)行的,也就是說如果你的項(xiàng)目中一個(gè)C文件都沒有,那么你的項(xiàng)目將無(wú)法編譯,連接
2、器是以目標(biāo)文件為單位,它將一個(gè)或多個(gè)目標(biāo)文件進(jìn)行函數(shù)與變量的重定位,生成最終的可執(zhí)行文件。為了生成一個(gè)最終的可執(zhí)行文件,就需要一些目標(biāo)文件,也就是首先要有C文件,而這些C文件中又需要一個(gè)main()函數(shù)作為可執(zhí)行程序的入口,那么我們就從從這一個(gè)C文件入手,引入頭文件概念。假定這個(gè)C文件內(nèi)容如下:#include#include"mytest.h"intmain(intargc,char**argv){test=25;printf("test...........%d",test);}頭文件"mytest.h"
3、包含如下內(nèi)容:inttest;現(xiàn)在以這個(gè)例子來(lái)講解編譯器的工作:1.預(yù)處理階段:編譯器以C文件作為一個(gè)單元,首先讀這個(gè)C文件,發(fā)現(xiàn)第一句與第二句是包含一個(gè)頭文件,就會(huì)在所有搜索路徑中尋找這兩個(gè)文件,找到之后,就會(huì)將相應(yīng)頭文件中的宏,變量,函數(shù)聲明,嵌套的頭文件包含等,進(jìn)行依賴關(guān)系檢測(cè),并進(jìn)行宏替換,看是否有重復(fù)聲明與定義的情況發(fā)生,最后將那些文件中所有的東東全部掃描進(jìn)這個(gè)當(dāng)前的C文件中,形成一個(gè)中間"C文件"2.編譯階段,在上一步中相當(dāng)于將第二個(gè)頭文件中的test變量掃描進(jìn)了一個(gè)中間C文件,那么test變量就變成了這個(gè)文件中的一個(gè)
4、全局變量,此時(shí)就將所有這個(gè)中間C文件的所有變量,函數(shù)分配空間,將各個(gè)函數(shù)編譯成二進(jìn)制碼,按照特定目標(biāo)文件格式生成目標(biāo)文件,在這種格式的目標(biāo)文件中進(jìn)行各個(gè)全局變量,函數(shù)的符號(hào)描述,將這些二進(jìn)制碼按照一定的標(biāo)準(zhǔn)組織成一個(gè)目標(biāo)文件3.連接階段,將上一步成生的各個(gè)目標(biāo)文件,根據(jù)一些參數(shù),連接生成最終的可執(zhí)行文件,主要的工作就是重定位各個(gè)目標(biāo)文件的函數(shù),變量等,相當(dāng)于將個(gè)目標(biāo)文件中的二進(jìn)制碼按一定的規(guī)范合到一個(gè)文件中。再回到C文件與頭文件各寫什么內(nèi)容的話題上:一般都在頭件中進(jìn)行函數(shù)聲明,變量聲明,宏聲明,結(jié)構(gòu)體聲明呢?而在C文件中去進(jìn)行變量
5、定義,函數(shù)實(shí)現(xiàn)。理論上來(lái)說C文件與頭文件里的內(nèi)容,只要是C語(yǔ)言所支持的,無(wú)論寫什么都可以的,比如你在頭文件中寫函數(shù)體,只要在任何一個(gè)C文件包含此頭文件就可以將這個(gè)函數(shù)編譯成目標(biāo)文件的一部分(編譯是以C文件為單位的,如果不在任何C文件中包含此頭文件的話,這段代碼就形同虛設(shè)),你可以在C文件中進(jìn)行函數(shù)聲明,變量聲明,結(jié)構(gòu)體聲明,這也不成問題?。?!那為何一定要分成頭文件與C文件呢?又為何一般都在頭件中進(jìn)行函數(shù)聲明,變量聲明,宏聲明,結(jié)構(gòu)體聲明呢?而在C文件中去進(jìn)行變量定義,函數(shù)實(shí)現(xiàn)呢?原因如下:1.如果在頭文件中實(shí)現(xiàn)一個(gè)函數(shù)體,那么如果
6、在多個(gè)C文件中引用它,而且又同時(shí)編譯多個(gè)C文件,將其生成的目標(biāo)文件連接成一個(gè)可執(zhí)行文件,在每個(gè)引用此頭文件的C文件所生成的目標(biāo)文件中,都有一份這個(gè)函數(shù)的代碼,如果這段函數(shù)又沒有定義成局部函數(shù),那么在連接時(shí),就會(huì)發(fā)現(xiàn)多個(gè)相同的函數(shù),就會(huì)報(bào)錯(cuò)2.如果在頭文件中定義全局變量,并且將此全局變量賦初值,那么在多個(gè)引用此頭文件的C文件中同樣存在相同變量名的拷貝,關(guān)鍵是此變量被賦了初值,所以編譯器就會(huì)將此變量放入DATA段,最終在連接階段,會(huì)在DATA段中存在多個(gè)相同的變量,它無(wú)法將這些變量統(tǒng)一成一個(gè)變量,也就是僅為此變量分配一個(gè)空間,而不是多
7、份空間,假定這個(gè)變量在頭文件沒有賦初值,編譯器就會(huì)將之放入BSS段,連接器會(huì)對(duì)BSS段的多個(gè)同名變量?jī)H分配一個(gè)存儲(chǔ)空間3.如果在C文件中聲明宏,結(jié)構(gòu)體,函數(shù)等,那么我要在另一個(gè)C文件中引用相應(yīng)的宏,結(jié)構(gòu)體,就必須再做一次重復(fù)的工作,如果我改了一個(gè)C文件中的一個(gè)聲明,那么又忘了改其它C文件中的聲明,這不就出了大問題了,程序的邏輯就變成了你不可想象的了,如果把這些公共的東東放在一個(gè)頭文件中,想用它的C文件就只需要引用一個(gè)頭文件就行了,要改某個(gè)聲明的時(shí)候,只需要?jiǎng)右幌骂^文件就行了這樣豈不方便。再說頭文件,頭文件是一種文本文件,使用文本編
8、輯器將代碼編寫好之后,以擴(kuò)展名.h保存就行了。如上所述頭文件中一般放一些重復(fù)使用的代碼,例如函數(shù)聲明,變量聲明,常數(shù)定義,宏的定義等等。在實(shí)際編程中,我們?cè)谛枵{(diào)用該c文件相對(duì)應(yīng)的頭文件用#include語(yǔ)句將頭文件包含進(jìn)來(lái)引用時(shí),也就是相當(dāng)于將頭文