#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