參考博客:html
c語言中.h文件和.c文件的解析 程序員
編譯器的工做過程函數
最近在作一個稍微有些複雜的項目。涉及到的函數、結構體、變量等比較多。一般,我編寫c/c++項目的方式是,有一個main.c文件,該文件的main函數做爲接口,調用其餘函數。全部其餘函數按功能,分別放在不一樣的.h文件中,這樣的方式在編譯和運行上確定是沒有什麼問題的。編碼
隨着項目編寫的深刻,結構、邏輯以及變量的日趨複雜,總感受上述方式的實現仍然不夠清晰而且會致使一些冗餘。突然記起,在課堂上,老師提到過,.h文件通常用來存放函數聲明和變量名,那麼爲何我在.h文件中實現函數不會有問題呢?其餘.c文件和main.c文件又有什麼關係呢?這些,都使我不得不從新思考.h文件和.c文件的做用和關係。spa
要理清.h文件的做用,咱們不妨看看.h文件的由來:.net
「在編譯器只認識.c(.cpp))文件,而不知道.h是何物的年代,那時的人們寫了不少的.c(.cpp)文件,漸漸地,人們發如今不少.c(.cpp)文件中的聲明語句就是相同的,但他們卻不得不一個字一個字地重複地將這些內容敲入每一個.c(.cpp)文件。但更爲恐怖的是,當其中一個聲明有變動時,就須要檢查全部的.c(.cpp)文件。
因而人們將重複的部分提取出來,放在一個新文件裏,而後在須要的.c(.cpp)文件中敲入#include XXXX這樣的語句。這樣即便某個聲明發生了變動,也再不須要處處尋找與修改了。由於這個新文件,常常被放在.c(.cpp)文件的頭部,因此就給它起名叫作「頭文件」,擴展名是.h。
在咱們語言的初學階段,每每咱們的程序只有一個.c的文件或這不多的幾個,這時咱們就不多遇到頭文件組織這個頭疼的問題,隨着咱們程序的增長,代碼 量到了幾千行甚至幾萬行,文件數也愈來愈多。這時這些文件的組織就成了一個問題,其實說白了這些文件的組織問題從理論上來講是軟件工程中的模塊設計等等的問題。」(引自c語言項目中.h文件和.c文件的關係)設計
由上能夠看出,.h文件最初就是用來給變量和函數提供一些全局性的聲明,這些聲明被其餘.c文件共享,方便變量和聲明的修改,使得大型代碼邏輯更清晰更易於維護。所以.h文件中通常是聲明,不多有代碼的具體實現。htm
那麼爲何在.h文件中實現函數也不會出錯呢?在.h文件中實現函數與在.c文件中實現函數有什麼區別和聯繫呢?普通的.C文件和包含main函數的c文件有什麼區別和聯繫呢?blog
要解決上述問題,首先必須弄清編譯器的工做原理。編譯器的最終目的是將程序員編寫的源代碼轉換成機器可以識別運行的二進制機器碼。大致上分,能夠分爲4個步驟:
1.頭文件的預編譯,預處理
編譯器在編譯源代碼時,會先編譯頭文件,保證每一個頭文件只被編譯一次。
在預處理階段,編譯器將c文件中引用的頭文件中的內容所有寫到c文件中。
2.詞法和語法分析(查錯)
3.編譯(彙編代碼,.obj文件)
轉化爲彙編碼,這種文件稱爲目標文件。後綴爲.obj。
4.連接(二進制機器碼,.exe文件)
將彙編代碼轉換爲機器碼,生成可執行文件。
更詳細具體的流程可參考編譯器的工做過程
在編譯過程當中,.h文件中的全部內容會被寫到包含它的.c文件中,而全部的.c文件以一個共同的main函數做爲可執行程序的入口。
所以,在.h文件中編寫函數實現並不會出錯,至關於全部.h的內容最後都被寫到了main.c文件中。
可是爲了邏輯性、易於維護性以及一些其餘目的(可參考c語言中.h文件和.c文件的解析 ),通常在.h文件中寫函數的聲明,在.c文件中編寫函數的實現。