關於c語言頭文件
c語言的頭文件是以".h"后綴命名的文件,里面包含了宏定義、變量定義和函數聲明等等。
頭文件相當於多個.c文件直接交流的橋梁,使得不同的編譯單元可以相互通信。
為什么要有頭文件?
我們在編寫c程序的時候,有時需要把一個程序拆分成多個.c文件,不同文件之間的函數如何調用成了問題,編譯器如何知道我們正確地調用函數?函數在哪里?
一系列的問題促使了頭文件的產生。
有人會問,像Java,Python,C#這些語言都沒有頭文件,不都活得好好的嗎?C語言的頭文件意義何在?
第一:歷史原因
c語言是一門古老的語言,在幾十年前,當我們的程序有多個源文件的時候,編譯器如何在眾多編譯單元里面找出所有函數?這在當時,計算機無論是存儲空間還是運算能力都無法達到這個要求。所以我們需要手動把一些函數的聲 明,宏定義等等需要在編譯時用到的東西放到一個文件里面,這個文件就是頭文件(當然可以有多個)。
有了頭文件,編譯器就可以在編譯的過程中少花一點時間和空間,這與現在編譯器應該替我們做更多的事這一觀念相違背,但是在當時限於技術和條件,程序員們不得不這么做。寫程序就是這樣,程序員和編譯器總有一個累死。
當然,頭文件的作用不僅限於函數聲明,在編譯階段頭文件的具體作用后文會討論。
第二:c語言自身的開發場景
c語言屬於一門造輪子的語言,各種場景都能用。放在現如今也有一些對內存限制較嚴格的開發場景:嵌入式,內核等等。說白了,就是不給硬件太大壓力。
第三:編譯需要
編譯器在編譯文件的時候,需要頭文件提供一些信息,這點的作用后文會提及。
第四:編程需要
使用頭文件有利於模塊化程序設計,使程序利於維護和拓展
(下面兩點引自知呼:)
頭文件能加強類型安全檢查。若某個接口的實現或使用方式與頭文件中的聲明不一致,編譯器就會指出錯誤。這一簡單的規則能大大減輕程序員調試、改錯的負擔。
通過頭文件調用庫功能。在很多場合,源代碼不便(或不准)向用戶公布,只要向用戶提供頭文件和二進制庫即可。用戶只需按照頭文件中的接口聲明來調用庫功能,而不必關心接口如何實現。編譯器會從庫中提取相應的代碼。
頭文件里面有什么?
一般來說,頭文件里面會包含函數聲明,宏定義,變量定義,條件預處理。頭文件里面還可以包含其它的頭文件。基本上就是這些,沒有什么特殊的,和我們平時在編寫.c文件的時候一模一樣。
這里討論一個問題:我們所看到的大部分頭文件里面只有函數聲名,沒有具體實現,但是其實頭文件里面可以提供具體的函數實現,那么我們要不要這樣做呢?
答案是盡量不要!
假如我們有兩個文件同時包含了這個頭文件並一起編譯,就會有error產生。比如,你有一個c文件叫main.c,一個c文件叫test.c,兩個文件都包含頭文件header.h,里面實現了某個內容.編譯時我們一起編譯這兩個文件,這就相當於 在這兩個.c文件里面同時插入了一模一樣的header.h文件的內容,屬於重復定義。關於這點可以看一下c語言的命名管理機制。
頭文件的編寫及組織原則
首先我們來看一個簡單的頭文件定義:
//max.h
int max(int , int);
在max.h文件里面,我們聲明了一個函數max,該頭文件對應的.c文件為max.c,max.c文件代碼如下:
int max(int x, int y) {
return x > y ? x : y; }
在main.c里面,我們通過包含max.h,然后調用max函數:
#include "max.h"
int main(void) { max(10);
return 0; }
這就是一個簡單的頭文件使用的例子。當然,嚴格一點,我們需要在max.h文件里面使用預處理判斷語句,判斷max.h文件是否被定義過了。這點可以參考c語言的預處理指令。
關於在頭文件中定義宏,聲明變量等等操作大家可以自己嘗試,下面主要討論頭文件的組織原則:
頭文件不要太大。如果頭文件太大,會嚴重降低編譯速度!!所以在頭文件中盡量不要包含其它頭文件,應在所使用的頭文件的.c文件中包含。
源文件中實現變量、函數的定義,並指定鏈接范圍。頭文件中書寫外部需要使用的全局變量、函數聲明及數據類型和宏的定義。
對於大量的宏定義,函數聲明等,應該使用多個頭文件分離,或者按照關系緊密程度組織頭文件。
頭文件名應盡量與實現功能的源文件相同,即module.c和module.h。但源文件不一定要包含其同名的頭文件。
頭文件適合放置接口的聲明,不適合放置實現。 變量的聲明盡量不要放在頭文件,盡量不要使用全局變量作為接口。變量是模塊的內部實現細節,不應通過頭文件聲明的方式直接暴露給外部,應通過函數接口的方式對外暴露。
頭文件應自包含(自包含就是任意一個頭文件均可獨立編譯)
關於c語言頭文件,暫時討論至此,頭文件的其它用法及更詳細的代碼展示會放到“淺談c語言頭文件(2)”中進行討論
本文部分內容來源與網絡,侵權必刪;文章如有批漏或錯誤,歡迎留言提醒