預處理包含在代碼的程序之前,有一個哈希標志(#)。這些線不是程序語句但是是預處理指令。預處理器的匯編代碼實際開始編譯代碼之前是解決所有這些指令,任何的代碼實際上是通過固定的語句生成。
這些預處理指令只能在一個單一的代碼行中。當遇到一個換行符,預處理器指令結束。預處理器指令結束沒有分號(;)。預處理器指令可以延長到超過一行的唯一方法就是前面的換行符在行尾的反斜杠(/)。
定義預處理器宏可以用#define。它的語法是:
#define identifier replacement當處理器遇到這個指令,它在剩下的代碼中identifier 就被replacement代替,替換成后面的。這個replacement 可以是表達式、語句、塊或簡單的任何東西。預處理器不能準確理解C++,它只是簡單地用replacement取代identifier 。
#define TABLE_SIZE 100int table1[TABLE_SIZE];int table2[TABLE_SIZE];經過預處理器取代了table_size,代碼變得相當于:
int table1[100];int table2[100];# define 也可以用參數來定義函數:
#define getmax(a,b) a>b?a:b任何有getmax的地方都將被后面的表達式所替換,而且更換每個參數的標識符,如果期望它是一個函數:
// function macro#include <iostream>using namespace std;#define getmax(a,b) ((a)>(b)?(a):(b))int main(){ int x=5, y; y= getmax(x,2); cout << y << endl; cout << getmax(7,x) << endl; return 0;}定義的宏不受塊結構的影響。宏直到它的未定義 undef預處理指令為止:
#define TABLE_SIZE 100int table1[TABLE_SIZE];#undef TABLE_SIZE#define TABLE_SIZE 200int table2[TABLE_SIZE];上述代碼相當于:
int table1[100];int table2[200];函數的宏定義在置換序列接受兩個特殊操作符(#和##): 操作符#,后面為一個參數的名稱,是由一個包含該參數字符串替換了(如果包含在雙引號):
#define str(x) #xcout << str(test);可以理解為:
cout << "test";操作符##需要兩個參數,并且它們之間沒有空白:
#define glue(a,b) a ## bglue(c,out) << "test";可以等效為:
cout << "test";因為預處理器在C++任何語法檢查都會發生替換,宏定義可以是一個棘手的特征。但是,要注意的是:很大程度上依賴于復雜的宏可能使得代碼不可讀,因為這樣使得語法在C++許多場合中不同于正常表達。
這些指令如果滿足某一條件允許包含或丟棄程序的部分代碼。 # ifdef允許只有宏指定為參數程序的一個部分是進行編譯,不管它的值。例如:
#ifdef TABLE_SIZEint table[TABLE_SIZE];#endif在這種情況下,代碼int table [ table_size ],只有table_size先通過#定義,才能被編譯。如果未定義,則該行將不包含在程序編譯中。 #ifndef 則是完全相反的:如果指定的標識符之前還未定義,那么# ifndef和# endif指令之間的代碼只編譯。例如:
#ifndef TABLE_SIZE#define TABLE_SIZE 100#endifint table[TABLE_SIZE];在這種情況下,如果到了這段代碼,TABLE_SIZE 宏尚未被定義,它就被定義為值100。如果它已經存在,它將保持其先前的值,#指令不被執行。
其他的#if, #else and #elif (i.e., “else if”) (即“如果”)指令為指定要滿足的部分代碼被編譯的一些條件。條件#if或# elif只能是常量表達式,包括宏觀的表達。例如:
#if TABLE_SIZE>200#undef TABLE_SIZE#define TABLE_SIZE 200#elif TABLE_SIZE<50#undef TABLE_SIZE#define TABLE_SIZE 50#else#undef TABLE_SIZE#define TABLE_SIZE 100#endifint table[TABLE_SIZE];注意if, #elif 和#else是如何同結束指令 #endif相結合使用的。
對# ifdef和##ifndef還可以通過使用特殊的運營商定義的實現!分別在任何#if或#elif處進行defined :
#if defined ARRAY_SIZE#define TABLE_SIZE ARRAY_SIZE#elif !defined BUFFER_SIZE#define TABLE_SIZE 128#else#define TABLE_SIZE BUFFER_SIZE#endif編譯程序時,編譯過程中會出現一些錯誤,編譯器會顯示一個錯誤信息,其中引用了錯誤發生的文件名和行號,因此很容易找到產生錯誤的代碼。
#line指令允許我們控制這些事情,包括行號的代碼信息,以及我們希望文件名時出現一個錯誤發生位置。其格式是:
#line number "filename"這里number 被分配到下一個代碼行的新行號。連續行的行號將從這一點上逐點增加。 “filename”是一個可選參數,允許重新定義要顯示的文件名。例如:
#line 20 "assigning variable"int a?;此代碼將生成一個錯誤,將顯示為錯誤的文件“assigning variable”,第20行。
這個指令發生的時候中止編譯過程,產生一個編譯錯誤,可以指定為參數:
#ifndef __cplusplus#error A C++ compiler is required!#endif本例如果沒有定義的宏名__cplusplus中止編譯過程,(宏的名字是在所有的C++編譯器默認的定義)。
這個指令已經在本教程的其他部分經常出現,一個#include預處理器指令可以取代它指定特定頭文件的全部內容。有兩種方式使用#include:
#include <header>#include "file"在第一種情況下,在角括號之間指定header。這是用于包括安裝的頭文件,如標準庫頭文件(iostream,string,…)。頭文件是否為真實的文件或存在于其他位置是implementation-defined,在任何情況下,它們都應正確地包含在這個指令中。
在第二個 #include 使用引號,并包括一個文件。該文件以搜索的方式執行定義,該文件通常包括在當前路徑。在未找到文件的情況下,編譯器將指令解釋為包含頭<>的內容,就像引號(“”)被“<>”替換為。
此指令用于指定編譯器的不同選項。這些選項是指你使用的特定的平臺和編譯器。參考相關手冊或編譯器的更多信息,可以得到#pragma的更多用法參考。
如果編譯器不支持#pragma的具體參數,它會被忽略,不產生語法錯誤。
下面的宏的名字定義為(他們都開始和結束于兩個下劃線,_): 
下列宏可任意定義,通常取決于是否有可用的功能:

特定實現可以定義附加常數。 例如:
// standard macro names#include <iostream>using namespace std;int main(){ cout << "This is the line number " << __LINE__; cout << " of file " << __FILE__ << "./n"; cout << "Its compilation began " << __DATE__; cout << " at " << __TIME__ << "./n"; cout << "The compiler gives a __cplusplus value of " << __cplusplus; return 0;}結果為:
This is the line number 7 of file /home/jay/stdmacronames.cpp.Its compilation began Nov 1 2005 at 10:12:29.The compiler gives a __cplusplus value of 1新聞熱點
疑難解答
圖片精選