C 語言中以 #
開頭的就是預處理指令,例如 #include
。web
全部的預處理指令都會在 GCC 編譯過程的預處理步驟解析執行,替換爲對應的內容。在下一步編譯過程當中,看不到任何預處理信息,只須要對獨立的程序文件進行操做便可。svg
#include 頭文件
#define 宏名 宏體
#define MY_VAR 3+4
,使用的時候若是是這樣 int i = MY_VAR * 5
,會在預處理時替換爲 int i = 3+4 * 5
,最終獲得的 i 是23。而 #define MY_VAR (3+4)
則無次問題#define MY_FUN(x) (3+x)
,使用 int i = MY_FUN(4)*5
獲得的 i 是 35。#ifdef #ifndef #else #endif
例如,對於這個 C 文件:函數
#include <stdio.h> int main() { printf("file is:%s, function is:%s, line is:%d, %s, %s", __FILE__, __FUNCTION__, __LINE__, __DATE__, __TIME__); }
執行結果以下:ui
file is:define.c, function is:main, line is:5, Jan 19 2019, 15:10:57
預處理時,會把全部出現宏名的地方自動替換爲對應的宏值。spa
#define 宏名 宏值
宏定義的規則:debug
#define PI 3.14 #define PI2 PI * 2
\
換行,例如:#define PRT printf("%f ", PI); \ printf("%f", PI2)
#define DEBUG
;
,不然會被替換致使異常。綜合示例:調試
#include <stdio.h> #define PI 3.14 #define PI2 PI*2 #define PRT printf("%f ", PI); \ printf("%f\n", PI2) #define MIN(a, b) ((a) < (b) ? (a) : (b)) int main() { PRT; printf("%d", MIN(2+3*5, 666)); }
能夠帶一個或多個參數。有參數的宏的原則是:code
一切地方都有加括號,放在由於運算的優先級致使異常xml
#include <stdio.h> #define MIN(a, b) ((a) < (b) ? (a) : (b)) #define FUN1(a) (a * 5) #define FUN2(a) (a) * 5 int main() { printf("%d\n", MIN(2+3*5, 666)); printf("%d\n", FUN1(5 + 6)); //5 + 6 * 5 = 35 printf("%d\n", 100 / FUN2(5)); //100 / 5 * 5 = 100 }
可使用 inline 內聯函數替代有參數的宏定義,速度快的同時還能夠檢查參數類型。token
對於 C99 以後的版本,可使用常量定義來代替無參數的宏定義:
const double PI 3.14;
經過條件預處理指令,能夠在預處理階段控制要編譯的代碼,從而實現條件預編譯。對編譯器來講這個步驟是透明的,它只須要編譯全部它看見的代碼便可。例如:
#include <stdio.h> #define DEBUG int main() { #ifdef DEBUG printf("debug info");// 只有定義了 DEBUG,纔會執行這段代碼 #endif printf("hello world\n"); return 0; }
固然,在文件中直接定義宏的話,每次都有修改源文件,不靈活。GCC 提供了一個指定宏定義的選項 gcc -D
,例如 gcc -DDEBUG -o build 1.c
會自動在代碼中添加一段定義 DEBUG 的指令 #define DEBUG
,這樣就能夠在上面的源代碼中刪除 #define DEBUG
這一行了。
在宏體中(宏名中不可使用)可使用一個或兩個 #
做爲前綴。
示例:
#include <stdio.h> #define MY1(x) #x //傳入的參數轉爲字符串 #define MY2(x) day##x //傳入的參數自動拼接到 day 後面,例如出入1時爲 day1 int main() { int day1 = 666; printf(MY1(abc\n)); // 打印 abc 字符串後換行 printf("%d", MY2(1));// 打印 666,即變量 day1 }