關於預處理的“常識”
預處理並不是編譯,也不是“預編譯”。
預處理並不是每個語言都有的。
C/C++預處理僅僅是把源程序劃分和整理成一個個的段(phase),並不進行編譯。
預處理器在UNIX傳統中通常縮寫爲PP,在自動構建腳本中C預處理器被縮寫爲CPP的宏指代。爲了不造成歧義,C++(c-plus-plus) 經常並不是縮寫爲CPP,而改成CXX。
C語言預處理符號
ANSI C標準要求支持的預處理符號包括:
#define、#undef(宏定義), #include(文件包含), #if、#else、#elif、#endif、#ifdef、#ifndef(條件編譯), #line(行控制), #error(錯誤處理), #pragma(實現相關), #(轉義),##(參數連接)。
宏定義的注意事項
試圖使用宏去定義註釋符號是不行的,例如以下代碼:
#define BSC // #define BMC /* #define EMC */ BSC my single-line comment BMC my multi-line comment EMC
因爲註釋先於預處理指令處理,當展開這些宏定義的時候自然會出現一堆錯誤。
宏定義表達式的時候一定不能吝嗇括號。這個不用解釋了。
宏定義的時候宏名中最好不要有空格。下面的定義會帶來很多麻煩:
#define SUM (x) ((x)*(x))
一旦使用了#undef撤銷宏,則後面的代碼都不能使用這個宏,除非再次定義。此外,如果沒有#undef的情形下就直接再次定義,後來的定義會覆蓋掉前面的定義。下面代碼中的c值是4:
#include <stdio.h> #define X 3 #define Y X*2 #undef X #define X 2 int c = Y; int main(int argc, char** argv){ printf("%d",c) ; return 0; }
宏僅在使用的時候展開,否則即使定義有問題,也不會編譯出錯。如果把上面代碼中的第二個#define註釋掉,並把C的值賦值爲0,即撤銷了X定義,也不會報錯,因爲沒有使用Y,也就不會展開。
#pragma的常用參數
message:用於在編譯窗口輸出信息中顯示對應信息。下面是一個典型的應用:
#ifdef _X86 #pragma message("x86 macro is activated."); #endif
code_seg:在開發驅動程序的時候會用到。
once: 指定(確保)僅編譯一次該文件(一般是頭文件)。
hdrstop:表示不編譯後面的頭文件。
pack:指定內存對齊參數。
#符號和##符號
#符號用於轉義。這麼說起來不好理解,看例子:
#define PRTSQR(x) printf("The sqr of x is %d.\n", ((x)*(x)));
如果執行PRTSQR(4),則這句代碼的輸出是:
The sqr of x is 16.
如果希望顯示參數的值,那麼在字符串中的字符x前面加一個#並加一個引號,即:
#define PRTSQR(x) printf("The sqr of "#x" is %d.\n", ((x)*(x)));
輸出結果就成了:
The sqr of 4 is 16.
##運算符用於連接,例如下面的宏:
#define XNAME(n) x##n int XNAME(8);
上面的第二行代碼會被展開爲x8。
關於預處理符號先總結到這裏。