#define,#error,#include,#if,#else,#elif,#endif,#ifdef,#ifndef,#undef,#line,#pragma等。很是明顯,全部預處理命令均以符號#開頭函數
#line用於重置由__LINE__和__FILE__宏指定的行號和文件名。優化
#error指令使預處理器發出一條錯誤消息,該消息包含指令中的文本.這條指令的目的就是在程序崩潰以前可以給出必定的信息。spa
#pragma的做用是設定編譯器的狀態或者是指示編譯器完成一些特定的動做。.net
C++宏體中出現的#,#@,##指針
宏體中,#的功能是將其後面的宏參數進行字符串化操做(Stringfication),簡單說就是在對它所引用的宏變量經過替換後在其左右各加上一個雙引號。code
而##被稱爲鏈接符(concatenator),用來將兩個Token鏈接爲一個Token。注意這裏鏈接的對象是Token就行,而不必定是宏的變量。好比你要作一個菜單項命令名和函數指針組成的結構體對象
#define命令是C語言中的一個宏定義命令,它用來將一個標識符定義爲一個字符串,該標識符被稱爲宏名,被定義的字符串稱爲替換文本。遞歸
(1) 簡單的宏定義:
#define <宏名> <字符串>
例: #define PI 3.1415926
(2) 帶參數的宏定義
#define <宏名> (<參數表>)<宏體>字符串
在程序中出現的是宏名,在該程序被編譯前,先將宏名用被定義的字符串替換,這稱爲宏替換,替換後才進行編譯,宏替換是簡單的替換。get
宏定義用法
#define Conn(x,y) x##y
#define ToChar(x) #@x
#define ToString(x) #x
int n = Conn(123,456); 結果就是n=123456;
char a = ToChar(1);結果就是a='1';
作個越界試驗char a = ToChar(123);結果是a='3';
char* str = ToString(123132);就成了str="123132";
在標準C以及各中編譯器中定義了一些對象宏, 這些宏的名稱以"__"開頭和結尾, 而且都是大寫字符. 這些預約義宏能夠被#undef, 也能夠被重定義。
歸納起來GCC中可以使用的預約義宏涵蓋了以下幾方面的信息:
一、宿主的信息:GNU的版本,編譯器的版本,類型的相關信息,字節序信息等。
二、編譯動做的信息:編譯的日期、時間;編譯時是否進行了時間或空間上的優化;定義的inline是否被編譯器執行等。
三、文件的信息:文件名稱、函數名稱、行數信息、文件最後修改時間等等。
四、計數信息:__COUNTER__,__INCLUDE_LEVEL__等。
一、__FILE__ 表明當前源代碼文件名的字符串文字 ,包含了詳細路徑,如G:/program/study/c+/test1.c
__LINE__ 表明當前源代碼中的行號的整數常量
__func__ 當前所在函數名,在編譯器的較高版本中支持
__FUNCTION__ 當前所在函數名
三、__DATE__,__TIME__
__DATE__ 進行預處理的日期(「Mmm dd yyyy」形式的字符串文字,如May 27 2006)
__TIME__ 源文件編譯時間,格式微「hh:mm:ss」,如:09:11:10;
四、__TIMESTAMP__
五、__GNUC__、__GNUC_MINOR__、__GNUC_MINOR__、__GNUC_PATCHLEVEL__
用於獲得GNU版本:
六、__VERSION__
用於獲得編譯器的版本
七、__COUNTER__
自身計數器,用於記錄之前編譯過程當中出現的__COUNTER__的次數,從0開始計數。經常使用於構造一系列的變量名稱,函數名稱等。
八、__INCLUDE_LEVEL__
用於表示文件被包含的計數,從0開始遞增,常做爲遞歸包含的限制條件。
九、__PRETTY_FUNCTION__ 非標準宏。這個宏比__FUNCTION__功能更強:
1)若用g++編譯C++程序, __FUNCTION__只能輸出類的成員函數名,不會輸出類名;而__PRETTY_FUNCTION__則會以 <return-type> <class-name>::<member-function-name>(<parameters-list>) 的格式輸出成員函數的詳悉信息(注: 只會輸出parameters-list的形參類型, 而不會輸出形參名).
2)若用gcc編譯C程序,__PRETTY_FUNCTION__跟__FUNCTION__的功能相同.
#define MACRO x123 #define RES MACRO##yy //RES結果是MACROyy,而咱們但願的是x123yy,這樣,把RES 改成 #define RES BOOST_PP_CAT(MACRO,yy)
#define B 1 #define C1 BOOST_PP_CAT(A, B) #define C2 BOOST_PP_CAT_SIMPLE(A, B) //C1是A1,而C2是AB。也就是說: //若是B不是宏,BOOST_PP_CAT和BOOST_PP_CAT_SIMPLE沒有區別; //若是B是宏,BOOST_PP_CAT_SIMPLE依然是直接鏈接,而BOOST_PP_CAT宏是先將B宏展開,而後鏈接。
BOOST_PP_SEQ_FOR_EACH宏,用於將一個序列中參數依次按照指定宏進行展開。
BOOST_PP_SEQ_FOR_EACH(macro, data, seq)
BOOST_PP_SEQ_FOR_EACH是一個重複項的宏。
若是序列是(a)(b)(c),則展開爲:
macro(r, data, a) macro(r, data, b) macro(r, data, c)
若是要求更高效率,可以使用BOOST_PP_SEQ_FOR_EACH_R
#include <boost/preprocessor/cat.hpp> #include <boost/preprocessor/seq/for_each.hpp> #define SEQ (w)(x)(y)(z) #define MACRO(r, data, elem) elem::GetInstance() BOOST_PP_SEQ_FOR_EACH(MACRO, _, SEQ) // expands to w::GetInstance() x::GetInstance() y::GetInstance() z::GetInstance()
BOOST_PP_EXPR_IIF