ANSI C 標準規定在 C 源程式中可加入「預處理命令」,以改善程式設計環境、提高編程效率。這些命令並非 C 語言本身的組成部分,無法直接編譯。編譯器會先對程式中的特殊命令進行「預處理」,移除所有預處理指令後,再對處理過的源程式進行常規編譯,產生可執行的目標代碼。
C 語言提供的預處理功能主要有三種:
- 宏定義
- 文件包含
- 條件編譯
分別由宏定義命令、文件包含命令、條件編譯命令實現,這些命令皆以「#」開頭。
用一個指定的標識符代表一個字串,一般形式:
#define 識別符 字串
範例:
#define PI 3.1415926
說明:
PI 取代「3.1415926」這個字串。預處理時,將程式中該命令出現後的所有 PI 替換為「3.1415926」;這些標識符稱為「宏名」。錯誤範例:
#define PI 3.14; ... area = PI * r * r;
宏展開後變為:
area = 3.14; * r * r; // 語法錯誤
帶參數的宏定義不僅進行字串替換,還要進行參數替換,一般形式:
#define 宏名(參數表) 字串
範例:
// 定義矩形面積 S,a 和 b 為變長 #define S(a,b) a*b ... area = S(3,2);
展開過程:程式中若帶有實參的宏(如 S(3,2)),按 #define 命令列中指定的字串從左到右置換。字串中包含形參(如 a、b)則用相應實參取代;非參數字符(如 *)則保留。
因此賦值語句展開為:
area = 3*2;
進階範例:
#define PI 3.14
#define S(r) PI*(r)*(r)
int _tmain(int argc, _TCHAR* argv[]) {
float a, area;
a = 2;
area = S(a+1); // 展開為 3.14*(a+1)*(a+1)
printf("r=%.2f,area=%.2f\n", a, area);
}
運行結果:
r=2.00,area=28.26
注意:宏名與帶參數的括號之間不應加空格,否則會變成不帶參數的宏定義,導致錯誤。例如:
#define S (r) 3.14*(r)*(r) ... area = S(a+1); // 展開為 3.14*(r)*(r)(a+1) 錯誤
所謂「文件包含」是指一個源檔案可將另一個源檔案的內容全部包含進本檔案。C 語言提供 #include 命令實現,一般形式:
#include <檔名>(一般為庫檔案)
#include "檔名"(使用者自定義檔案)
一般情況下,源程式中所有行都參與編譯,但有時只希望在滿足特定條件下才編譯,這就是「條件編譯」。可在滿足條件時編譯一組敘述,不滿足時編譯另一組。
#ifdef 識別符 程式段1 #endif
#ifdef 識別符 程式段1 #else 程式段2 #endif
#ifndef 識別符 程式段1 #endif
#if 表達式 程式段1 #else 程式段2 #endif
總結:預編譯功能是 C 語言特有的,有利於程式的可移植性,增加程式的靈活性。