關於預處理的「常識」
ide
預處理並非編譯,也不是「預編譯」。spa
預處理並非每一個語言都有的。code
C/C++預處理僅僅是把源程序劃分和整理成一個個的段(phase),並不進行編譯。內存
預處理器在UNIX傳統中一般縮寫爲PP,在自動構建腳本中C預處理器被縮寫爲CPP的宏指代。爲了避免形成歧義,C++(c-plus-plus) 常常並非縮寫爲CPP,而改爲CXX。開發
C語言預處理符號字符串
ANSI C標準要求支持的預處理符號包括:it
#define、#undef(宏定義), #include(文件包含), #if、#else、#elif、#endif、#ifdef、#ifndef(條件編譯), #line(行控制), #error(錯誤處理), #pragma(實現相關), #(轉義),##(參數鏈接)。io
宏定義的注意事項編譯
試圖使用宏去定義註釋符號是不行的,例如如下代碼:class
#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。
關於預處理符號先總結到這裏。