C++預處理
預處理器是指令,它的編譯器預處理指令給出的信息,實際編譯開始之前。
所有的預處理指令以#開頭,隻有空格字符可能線路上的預處理器指令之前出現。預處理指令不是C++語句,這樣它們就不會以一個分號(;)結束。
已經看到所有的例子#include指令。這個宏用於包括頭文件到源文件。
還有用C++的支持 如 #include, #define, #if, #else, #line,等預處理指令,讓我們看看重要指令:
#define預處理:
#define預處理指令創建符號常量。符號常量為 amacro指令的一般形式是:
#define macro-name replacement-text
當這條線出現在一個文件中,宏在該文件中的所有後續出現將被替換文本被替換的程序被編譯之前。例如:
#include <iostream> using namespace std; #define PI 3.14159 int main () { cout << "Value of PI :" << PI << endl; return 0; }
現在,讓我們測試這個代碼的預處理以看看結果,假設我們的源代碼文件,所以讓我們使用-E選項編譯並重定向結果test.p. 現在,如果檢查test.p,就會產生大量的信息,並在底部它的值被改為如下:
$gcc -E test.cpp > test.p ... int main () { cout << "Value of PI :" << 3.14159 << endl; return 0; }
函數宏:
可以使用的#define來定義一個宏將帶參數如下:
#include <iostream> using namespace std; #define MIN(a,b) (((a)<(b)) ? a : b) int main () { int i, j; i = 100; j = 30; cout <<"The minimum is " << MIN(i, j) << endl; return 0; }
如果我們編譯並運行上麵的代碼,這會產生以下結果:
The minimum is 30
條件編譯:
有幾個指令,可以用它來有選擇地進行編譯程序的部分源代碼。這個過程被稱為條件編譯。
有條件的預處理器結構很像if選擇結構。考慮下麵的預處理器的代碼:
#ifndef NULL #define NULL 0 #endif
可以用於調試目的編譯一個程序,並且可以調試打開或關閉使用單個宏如下:
#ifdef DEBUG cerr <<"Variable x = " << x << endl; #endif
將導致在程序編譯 cerr 聲明如果符號常量DEBUG 指令在 #ifdef DEBUG之前被定義。可以使用 #if 0 語句注釋掉程序的一部分,如下所示:
#if 0 code prevented from compiling #endif
讓我們試試下麵的例子:
#include <iostream> using namespace std; #define DEBUG #define MIN(a,b) (((a)<(b)) ? a : b) int main () { int i, j; i = 100; j = 30; #ifdef DEBUG cerr <<"Trace: Inside main function" << endl; #endif #if 0 /* This is commented part */ cout << MKSTR(HELLO C++) << endl; #endif cout <<"The minimum is " << MIN(i, j) << endl; #ifdef DEBUG cerr <<"Trace: Coming out of main function" << endl; #endif return 0; }
如果我們編譯並運行上麵的代碼,這會產生以下結果:
Trace: Inside main function The minimum is 30 Trace: Coming out of main function
#和##運算符:
#和##預處理器運算符是用C++提供和ANSI/ISO C的#操作符產生替代文本令牌轉換為用引號引起來的字符串。
考慮下麵的宏定義:
#include <iostream> using namespace std; #define MKSTR( x ) #x int main () { cout << MKSTR(HELLO C++) << endl; return 0; }
如果我們編譯並運行上麵的代碼,這會產生以下結果:
HELLO C++
讓我們來看看它是如何工作。這很容易理解,在C++預處理變成了一行:
cout << MKSTR(HELLO C++) << endl;
進入下麵一行:
cout << "HELLO C++" << endl;
##運算符是用來連接兩個標記。下麵是一個例子:
#define CONCAT( x, y ) x ## y
當CONCAT出現在程序中它的參數被連接起來,並用來取代宏。例如,CONCAT(HELLO,C++)被在節目改為“HELLO C++”,如下所示。
#include <iostream> using namespace std; #define concat(a, b) a ## b int main() { int xy = 100; cout << concat(x, y); return 0; }
如果我們編譯並運行上麵的代碼,這會產生以下結果:
100
讓我們來看看它是如何工作。這很容易理解,在C++預處理器轉換:
cout << concat(x, y);
進入下麵一行:
cout << xy;
預定義的C++宏:
C++提供了許多下麵提到的預定義宏:
宏 | 描述 |
---|---|
__LINE__ | 這包含程序的當前行號時,它被編譯 |
__FILE__ | 這包括當它被編譯的程序的當前文件名 |
__DATE__ | 這包含格式月/日/年,它是轉換源文件到目標代碼的日期的字符串 |
__TIME__ | 這包含一個字符串的形式,時:分:秒。即在該程序被編譯時 |
讓我們看看上述所有宏的例子:
#include <iostream> using namespace std; int main () { cout << "Value of __LINE__ : " << __LINE__ << endl; cout << "Value of __FILE__ : " << __FILE__ << endl; cout << "Value of __DATE__ : " << __DATE__ << endl; cout << "Value of __TIME__ : " << __TIME__ << endl; return 0; }
如果我們編譯並運行上麵的代碼,這會產生以下結果:
Value of __LINE__ : 6 Value of __FILE__ : test.cpp Value of __DATE__ : Feb 28 2011 Value of __TIME__ : 18:52:48