預處理指令:例如:#include<stdio.h> ? ?? #include<stdlib.h> ? ? ? ? ? ? ??#define MAX 20 ............. ?
? ? 因為他們由預處理器解釋的,所以稱作預處理指令。預處理器讀取源代碼,然后對其修改,并把修改過的源代碼傳給編譯器,再由編譯器編譯。在我們的例子中預處理器用庫函數stdio.h , stdlib.h的內容替換分別執行第一,二條預處理指令(#include),就像把庫函數的內容寫入到了源文件了一樣。同理,對于標識符MAX也一樣,在函數編譯階段,編譯器將所有的MAX都替換為20。
宏和標識符: ? ?標識符 ? #define ?NAME ?stuff ? ? ? ?
? ? ? ? ? ? ? ? ? ? ? ? ?宏 ? ? ? ? ?#define ?NAME(參數列表) ? stuff?
宏和標識符最主要的區別是宏有參數,而標識符沒有參數,他們共同的特點都是在編譯階段,只要遇見關鍵字NAME(NAME(參數列表))編譯器就替換成stuff),通常將宏名大寫,用以和函數區分。
宏的用法:#define定義了一個機制,宏允許把參數替換到文本中,這種實現我們通常成為宏或宏定義。我們需要注意宏的參數左“(”和宏名之間不能有空格, 例如:#define ?NAME ?(5) ? ?X ? 是錯誤的,因為編譯器會理解成標識符,而發生錯誤。還有就是宏的參數列表中的實際值會替換stuff中對應的值參數,為避免發生一些運算錯誤,我們需要在stuff中能加括號的地方都加上括號。
? #define ADD(x) ?x+x
? int sum=ADD(2)*10;
? ?printf("%d\n",sum);
輸出的結果不是40,而是22,這時應為宏實現替換的是 ? int ?sum=2+2*10,所以為了避免宏在替換時因為優先級引發的錯誤,我們在stuff
中能加括號的地方都加上括號,#define ADD(x) ? ((2)+(2)) ? ? ?“當參數太多時可以使用“\”(續航符)將參數寫在多行)”
"##":這個符號是把位于他兩邊的字符連成一個標識符,例:
#define ADD_SUM(sum_num,value) ? ? ? ? ? sum##sum_num=value
..................
ADD_SUM(5,10)代表的就是sum5=10,需要注意的是使用##鏈接生成的標識符必須是合法的。
#undef:這個指令用于移除一個宏定義,即一個現存的名字需要被重定義,則首先用#undef將舊定義移除。
命令行定義:允許你在命令行中定義符號,用于啟動編譯過程。例如:char arr[ARR_SIZT] ?ARR_SIZE可以再命令行中定義,以便于在不同條件下修改數組的大小。
條件編譯:可以選擇代碼的一部分是被正常編譯還是被忽略,
? ? ? ? ? ? ? ?#if ? ? ? ? ?connstant-expression(常量表達式,如果為真statement則編譯,否則跳過不編譯)
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?statement
? ? ? ? ? ? ? ?#endif
如果我們要編譯一段代碼,可以如下面所示,當我們編譯時將DEBUG設置為一,當我們要忽略時設置為0,這樣就可以將代碼保留在源文件中
#define DEBUG 1
#if DEBUG
printf(“%s”,*p);
#endif
條件編譯還支持#elif,#else的格式,以便于選擇不同的代碼段編譯:
?#if ? ? ? ? ?connstant-expression
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?statement
#elif ? ? ? connstant-expression
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?statement
....................
#else ? ? ?connstant-expression
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?statement
#endif
可以嵌套使用。
是否被定義:測試一個符號是否被定義,如果定義,則可執行某個操作,比如調用一個函數。
#ifdef ?symbol
?void ?fun();
#endif