C 頭文件
頭文件是副檔名為 .h 的文件,包含了 C 函數宣告和巨集定義,並被多個原始檔中引用共享。有兩種類型的頭檔:程式設計師編寫的頭檔和編譯器自備的頭檔。
在程式中要使用頭文件,需要使用 C 預處理指令 #include 來引用它。前面我們已經看過 stdio.h 頭文件,它是編譯器自帶的頭檔。
引用頭檔相當於複製頭檔的內容,但是我們不會直接在來源檔案中複製頭檔的內容,因為這麼做很容易出錯,特別在程式是由多個來源檔案組成的時候。
A simple practice in C 或 C++ 程式中,建議把所有的常數、巨集、系統全域變數和函數原型寫在頭檔中,在需要的時候隨時引用這些頭檔。
引用頭檔的語法
使用預處理指令 #include 可以引用使用者和系統頭檔。它的形式有以下兩種:
#include <file>
這種形式用於引用系統頭檔。它在系統目錄的標準清單中搜尋名為 file 的檔案。在編譯原始碼時,您可以透過 -I 選項把目錄前置在該清單前。
#include "file"
這種形式用來引用使用者頭檔。它在包含目前檔案的目錄中搜尋名為 file 的檔案。在編譯原始碼時,您可以透過 -I 選項把目錄前置在該清單前。
引用頭檔的動作
#include 指令會指示 C 預處理器瀏覽指定的檔案作為輸入。預處理器的輸出包含了已經產生的輸出,被引用檔案產生的輸出以及 #include 指令之後的文字輸出。例如,如果您有一個頭檔header.h,如下:
char *test (void);
和一個使用了頭檔的主程式program.c,如下:
int x;#include "header.h"int main (void){ puts (test ());}
編譯器會看到如下的令牌流:
int x;char *test (void);int main (void){ puts (test ());}
只引用一次頭檔
如果一個頭檔被引用兩次,編譯器會處理兩次頭檔的內容,這將會產生錯誤。為了防止這種情況,標準的做法是把檔案的整個內容放在條件編譯語句中,如下:
#ifndef HEADER_FILE#define HEADER_FILE the entire header file file#endif
這種結構就是通常所說的包裝器 #ifndef。當再次引用頭檔時,條件為假,因為 HEADER_FILE 已定義。此時,預處理器會跳過檔案的整個內容,編譯器會忽略它。
有條件引用
有時需要從多個不同的頭檔中選擇一個引用到程式中。例如,需要指定在不同的作業系統上使用的設定參數。您可以透過一系列條件來實現這一點,如下:
#if SYSTEM_1 # include "system_1.h"#elif SYSTEM_2 # include "system_2.h"#elif SYSTEM_3 ...#endif
但是如果頭檔比較多的時候,這麼做是很不妥當的,預處理器使用巨集來定義頭檔的名稱。這就是所謂的有條件引用。它不是用頭檔的名稱作為#include 的直接參數,您只需要使用巨集名稱代替:
#define SYSTEM_H "system_1.h" ... #include SYSTEM_H
SYSTEM_H 會擴展,預處理器會尋找system_1.h,就像#include 最初寫的那樣。 SYSTEM_H 可透過 -D 選項被您的 Makefile 定義。