19.1 #include
直接將標頭檔引入要編譯的程式碼。
標頭檔詳細定義資料結構,以及操作資料結構所需使用的函式名稱、參數及回傳值。
系統標頭檔由 <> 括起
使用者標頭檔由 "" 括起來
19.2 #define
將程式碼中所定義的字串換成另一字串。
一般習慣用 #define定義常數
用typedef定義資料類別,但也可用#define定義資料類別 Ex: #define Data int
透過#defien也可以定義巨集函式,Ex: #define marco(x) x * x
巨集函式非一個完整函式,只是進行字串的代換。
透過 gcc -E 指令可以將前置處理的結果送到螢幕。
例如程式碼
#define square(x) x * x
int main(void){
int i,j;
scanf("%d", &i);
scanf("%d", &j);
printf("%d\n", square(i+j));
執行gcc -E xxx.c 後得到的結果為
int main(void){
int i,j;
scanf("%d", &i);
scanf("%d", &j);
printf("%d\n", i+j * i+j);
return 0;
}
透過此方法可以驗證,巨集的使用是否得到預期的結果,以上的算式 i+j * i + j顯然不是我們想要的。
因此,可將巨集修正為 #define square(x) ((x) * (x))
int main(void){
int i,j;
scanf("%d", &i);
scanf("%d", &j);
printf("%d\n", ((i+j) * (i+j)));
return 0;
}
19.3 條件編譯 #if, #ifdef, #ifndef
依據前置處理指令#if來決定程式碼要不要編譯Ex:
#if condition
source code
#endif
只有condition為true時,上述的source code才會執行,常用於是否列印除錯資訊,例如:
#define DEBUG 0
...
#if DEBUG == 1
printf("This is debug message. \n");
#endif
透過控制DEBUG定義值,決定是否印出除錯資訊。
在編譯時使用-DSYMBOL=VALUE語法可以動態改變#define值,而不需要修改程式。Ex:
gcc -DDEBUG_LEVEL=8 program.c
如此在編譯時會將DEBUG_LEVEL 的值給定為8,但編譯器define,程式碼也define造成重複定義(redefine)。此時要透過#ifndef來處理。如果#ifndef後面的符號未被定義,則#ifndef到#endif中間的程式碼會被編譯,如果已經有定義,就不會被編譯。
透過#ifndef,我們使用下面的程式碼,來避免透過-D造成的重複定義問題,當編譯時未使用-D則DEBUG_LEVEL預設為4
#ifndef DEBUG_LEVEL
#define DEBUG_LEVEL 4
#endif
若程式中只是要單純的開關,透過前置處理指令#ifdef可以達成。
#ifdef DEBUG
source code
#endif
在編譯器中可以透過 gcc -DDEBUG program.c 來開關
在程式中可以透過 #define DEBUG來開關
使用#undef則可以將某符號取消定義。#undef DEBUG
19.4 __LINE__, __FILE__
__LINE__ 知道前置處理目前的行數
__FILE__ 知道前置處理目前的檔名
printf("file %s, line %d", __FILE__, __LINE__);
19.5 ##
##可以將前後的名字連在一起,例如: S_IR ## USR 會成為S_IRUSR
沒有留言:
張貼留言