標頭檔(英語:Header file),或包含檔案,是個在程式設計時,特別是在C語言C++中使用的檔案,通常是原始碼的形式,由編譯器在處理另一個原始檔的時候自動包含進來。一般來說,程式設計師通過編譯器指令將標頭檔包含進其他原始檔的開始(或頭部)。

標頭檔一般包含子程式變數和其他識別碼前置聲明。需要在一個以上原始檔中被聲明的識別碼可以被放在一個標頭檔中,並在需要的地方包含這個標頭檔。

C語言C標準函數庫C++C++標準函數庫中,標準庫函數習慣上在標頭檔中聲明。

作用

在大多數現代電腦程式語言中,程式可以被分成如子程式的更小的組件,這些組件可以通過許多物理源檔案分發,這些原始檔被單獨編譯。當一個子程式在定義的位置以外的地方被使用時,就需要引入前置聲明函數原型的概念。例如,一個函數在一個原始檔中有如下定義:

 int add(int a, int b)
 {
     return a + b;
 }

在另一個原始檔中參照的時候就可以聲明成這樣(包含函數原型):

 int add(int, int);
 
 int triple(int x)
 {
     return add(x, add(x, x));
 }

但是,這個簡單的方法需要程式設計師為add在兩個地方維護函數聲明,一個是包含函數實現的檔案,以及使用該函數的檔案。如果函數的定義改變了,程式設計師必須要更改散佈在程式中的所有的原型。

標頭檔提供了解決辦法。模組的標頭檔聲明作為模組公共介面一部分的每一個函數、對象以及資料類型。例如,在下面的情況下,標頭檔僅包含add的聲明。每一個參照了add的原始檔使用#include來包含標頭檔:

 /* File add.h */
 #ifndef ADD_H
 #define ADD_H
 
 int add(int, int);
 
 #endif /* ADD_H */
 /* File triple.c */
 #include "add.h"
 
 int triple(int x)
 {
     return add(x, add(x, x));
 }

這樣就減少了維護的負擔:當定義改變的時候,只須更新聲明的一個獨立副本(在標頭檔中的那個)。在包含對應的定義的原始檔中也可以包含標頭檔,這給了編譯器一個檢查聲明和定義一致性的機會。

 /* File add.c */
 #include "add.h"
 
 int add(int a, int b)
 {
     return a + b;
 }

通常,標頭檔被用來唯一指定介面,且多少提供一些文件來說明如何使用在該檔案中聲明的組件。在這個例子中,子程式的實現放在一個單獨的原始檔中,這個原始檔被單獨編譯。(在C和C++中有個例外,即行內函數。行內函數通常放在標頭檔中,因為大多數實現如果不知道其定義,在編譯時便無法適當的展開行內函數。)

替代

在訪問聲明在不同檔案中的識別碼問題上,標頭檔不是唯一的解決方法。他們也有缺點,當定義改變的時候可能仍然需要在兩個地方來修改(標頭檔和原始檔)。一些更新的語言(如Java)省略掉了標頭檔,而使用命名方案英語naming scheme(naming scheme),這就允許編譯器來定位與介面和類實現相關的原始檔。

#include陳述式的兩種語法

#include陳述式有兩種方式包含標頭檔,分別是使用雙引號" "與左右尖括號< >。其區別是(對於不是使用完全檔案路徑名的)標頭檔的搜尋順序不同:

使用雙引號" "的標頭檔的搜尋順序:

  1. 包含該#include陳述式的原始檔所在目錄;
  2. 包含該#include陳述式的已經打開的標頭檔的逆序(因為標頭檔可以#include另一個標頭檔構成一個序列);
  3. 編譯選項-I所指定的目錄
  4. 環境變數INCLUDE所定義的目錄

使用左右尖括號< >的標頭檔的搜尋順序:

  1. 編譯選項-I所指定的目錄
  2. 環境變數INCLUDE所定義的目錄

參見

外部連結