预处理器发生在程序被编译之前,所有的预处理器指令都以#开头。
1. #include预处理器指令:使指定文件的一个副本被包含到指令所在的位置。
#include <filename>与#include “filename”区别(简单不加以说明)
#include 指令用于包含标准类库头文件,也可以用于由多个源文件组成的程序。
2. #include 预处理器指令:符号常量
#define identifier replacement – text
e.g. #define PI 3.14159
3. #include 预处理器指令:宏
带一个实参宏的定义,用于计算一个圆的面积。
e.g. #define CIRCLE_AREA(x) (PI*(x)(x))
4. 条件编译
条件编译通常用于调试目的,程序员经常用输出语句来输出变量的值,从而可以验证程序的控制流。
e.g. #ifdef DEBUG
cerr << “variable x=” << x<<endl;
#endif
5. #error和#pragma预处理指令
#error 指令:
#error tokens会输出一条依赖于实现的消息,其中包含了这条指令中指定的标记,标记是由空格分隔的字符序列。
例如:#error 1 – out of range error 包含了6个标记
e.g. 在某种流行的C++编译器中,当处理#error指令时,指令中的标记就会作为错误的消息显示,预处理过程停止,程序不会被编译。
#pragma指令:
#pragma tokens 会导致发生由具体实现定义的操作,具体实现无法识别的pragma指令会被忽略。
e.g. 在VC++中加上#pragma pack(n)来处理内存以n字节对齐
6. #和##运算符
#和##在C和C++中都提供
#运算符会使替换文本标记被转换成双引号中的字符串
e.g. #define HELLO(x) cout<<"Hello,"#x<<endl;
当HELLO(john);出现在程序文本中,他会被扩展为cout<<" Hello,john"<<endl;
输出结果:Hello,john
注意:#运算符必须用于带是参的宏,因为它的操作数表示宏的实参。
##运算符将会将两个标记拼接起来
e.g. #define TOKENCONCAT(x,y) x##y 当TOKENCONCAT出现在程序中时,它的实参会被拼接在一起,用于替换宏
e.g. TOKENCONCAT(o,k)在程序中会被替换为ok
注:##运算符必须有2个操作数。
一道中科大洋的笔试题:
#define paster( n ) printf( "token" #n" = %d", token##n )
那么语句paster(9);展开后为printf( "token9 = %d", token9)
#include <stdio.h> #define paster( n ) printf( "token" #n" = %d", token##n ) int _tmain(intargc, _TCHAR*argv[]) { inttoken9 = 10; paster(9); getchar(); return0; }
运行结果为:token9 =10
参考文献:c++程序员教程 附录D