C語言中C檔案與h標頭檔案的關係

2021-05-28 08:45:27 字數 2257 閱讀 4763

簡單的說其實要理解c檔案與標頭檔案(即.h)有什麼不同之處,首先需要弄明白編譯器的工作過程,一般說來編譯器會做以下幾個過程:

1.預處理階段

2.詞法與語法分析階段

3.編譯階段,首先編譯成純彙編語句,再將之彙編成跟cpu相關的二進位製碼,生成各個目標檔案(.obj檔案)

4.連線階段,將各個目標檔案中的各段**進行絕對位址定位,生成跟特定平台相關的可執行檔案,當然,最後還可以用objcopy生成純二進位製碼,也就是去掉了檔案格式資訊。(生成.exe檔案)

編譯器在編譯時是以c檔案為單位進行的,也就是說如果你的專案中乙個c檔案都沒有,那麼你的專案將無法編譯,聯結器是以目標檔案為單位,它將乙個或多個目標檔案進行函式與變數的重定位,生成最終的可執行檔案,在pc上的程式開發,一般都有乙個main函式,這是各個編譯器的約定,當然,你如果自己寫聯結器指令碼的話,可以不用main函式作為程式入口!!!!

(main .c檔案目標檔案可執行檔案)

有了這些基礎知識,再言歸正傳,為了生成乙個最終的可執行檔案,就需要一些目標檔案,也就是需要c檔案,而這些c檔案中又需要乙個main函式作為可執行程式的入口,那麼我們就從乙個c檔案入手,假定這個c檔案內容如下:

#include

#include "mytest.h"

int main(int argc,char **argv)

標頭檔案內容如下:

int test;

現在以這個例子來講解編譯器的工作:

1.預處理階段:編譯器以c檔案作為乙個單元,首先讀這個c檔案,發現第一句與第二句是包含乙個標頭檔案,就會在所有搜尋路徑中尋找這兩個檔案,找到之後,就會將相應標頭檔案中再去處理巨集,變數,函式宣告,巢狀的標頭檔案包含等,檢測依賴關係,進行巨集替換,看是否有重複定義與宣告的情況發生,最後將那些檔案中所有的東東全部掃瞄進這個當前的c檔案中,形成乙個中間「c檔案」

2.編譯階段,在上一步中相當於將那個標頭檔案中的test變數掃瞄進了乙個中間c檔案,那麼test變數就變成了這個檔案中的乙個全域性變數,此時就將所有這個中間c檔案的所有變數,函式分配空間,將各個函式編譯成二進位製碼,按照特定目標檔案格式生成目標檔案,在這種格式的目標檔案中進行各個全域性變數,函式的符號描述,將這些二進位製碼按照一定的標準組織成乙個目標檔案

3.連線階段,將上一步成生的各個目標檔案,根據一些引數,連線生成最終的可執行檔案,主要的工作就是重定位各個目標檔案的函式,變數等,相當於將個目標檔案中的二進位製碼按一定的規範合到乙個檔案中再回到c檔案與標頭檔案各寫什麼內容的話題上:理論上來說c檔案與標頭檔案裡的內容,只要是c語言所支援的,無論寫什麼都可以的,比如你在標頭檔案中寫函式體,只要在任何乙個c檔案包含此標頭檔案就可以將這個函式編譯成目標檔案的一部分(編譯是以c檔案為單位的,如果不在任何c檔案中包含此標頭檔案的話,這段**就形同虛設),你可以在c檔案中進行函式宣告,變數宣告,結構體宣告,這也不成問題!!!那為何一定要分成標頭檔案與c檔案呢?又為何一般都在頭件中進行函式,變數宣告,巨集宣告,結構體宣告呢?而在c檔案中去進行變數定義,函式實現呢??原因如下:

1.如果在標頭檔案中實現乙個函式體,那麼如果在多個c檔案中引用它,而且又同時編譯多個c檔案,將其生成的目標檔案連線成乙個可執行檔案,在每個引用此標頭檔案的c檔案所生成的目標檔案中,都有乙份這個函式的**,如果這段函式又沒有定義成區域性函式,那麼在連線時,就會發現多個相同的函式,就會報錯

2.如果在標頭檔案中定義全域性變數,並且將此全域性變數賦初值,那麼在多個引用此標頭檔案的c檔案中同樣存在相同變數名的拷貝,關鍵是此變數被賦了初值,所以編譯器就會將此變數放入data段,最終在連線階段,會在data段中存在多個相同的變數,它無法將這些變數統一成乙個變數,也就是僅為此變數分配乙個空間,而不是多份空間,假定這個變數在標頭檔案沒有賦初值,編譯器就會將之放入bss段,聯結器會對bss段的多個同名變數僅分配乙個儲存空間

3.如果在c檔案中宣告巨集,結構體,函式等,那麼我要在另乙個c檔案中引用相應的巨集,結構體,就必須再做一次重複的工作,如果我改了乙個c檔案中的乙個宣告,那麼又忘了改其它c檔案中的宣告,這不就出了大問題了,程式的邏輯就變成了你不可想象的了,如果把這些公共的東東放在乙個標頭檔案中,想用它的c檔案就只需要引用乙個就ok了!!!這樣豈不方便,要改某個宣告的時候,只需要動一下頭檔案就行了

4.在標頭檔案中宣告結構體,函式等,當你需要將你的**封裝成乙個庫,讓別人來用你的**,你又不想公布原始碼,那麼人家如何利用你的庫呢?也就是如何利用你的庫中的各個函式呢??一種方法是公布原始碼,別人想怎麼用就怎麼用,另一種是提供標頭檔案,別人從頭檔案中看你的函式原型,這樣人家才知道如何呼叫你寫的函式,就如同你呼叫printf函式一樣,裡面的引數是怎樣的??你是怎麼知道的??還不是看人家的標頭檔案中的相關宣告啊!!!當然這些東東都成了c標準,就算不看人家的標頭檔案,你一樣可以知道怎麼使用

c語言中 h檔案和 c檔案的關係

在編譯器只認識.c cpp 檔案,而不知道.h是何物的年代,那時的人們寫了很多的.c cpp 檔案,漸漸地,人們發現在很多.c cpp 檔案中的宣告語句就是相同的,但他們卻不得不乙個字乙個字地重複地將這些內容敲入每個.c cpp 檔案。但更為恐怖的是,當其中乙個宣告有變更時,就需要檢查所有的.c c...

C語言與C 語言中的標頭檔案

標頭檔案 在c語言家族程式中,標頭檔案被大量使用。一般而言,每個c c程式通常由標頭檔案 header files 和定義檔案 definition files 組成。標頭檔案作為一種包含功能函式 資料介面 宣告的載體檔案,用於儲存程式的宣告 declaration 而定義檔案用於儲存程式的實現 i...

c語言中的標頭檔案

在系統架構時,常會包含標頭檔案.h和 檔案.c。這幾天閱讀了部分的c 對頭檔案有一些自己的想法,特意寫到了自己的 部落格中,畢竟知識是在於積累的。標頭檔案,在 編譯執行過程中,起到預先編譯的作用,在它裡面都會包含有這些內容。相關資料結構宣告 為增加 的維護性,我們會預先在標頭檔案中,把需要使用的資料...