一. 预处理器
预处理器指令是为编译器提供指令,以便在实际编译开始之前对信息进行预处理。所有的预处理器指令以#
开头,且在指令行的前面只能有空白字符。预处理器指令不是C++语句,因此它们不以分号;
结束。
在所有的示例中,您已经见过#include
指令。此宏用于将头文件包含到源文件中。
C++支持多种预处理器指令,例如#include
、#define
、#if
、#else
、#line
等。让我们来看一些重要的指令。
二. #define
预处理器
#define
预处理器指令用于创建符号常量。符号常量被称为宏,指令的一般形式如下:
#define macro-name replacement-text
当文件中出现这行代码时,该文件中的所有后续宏都将在编译前被替换为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
文件的底部,我们会看到宏被替换后的内容如下:
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
。您也可以使用#if 0
语句注释掉部分代码,如下所示:
#if 0
#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
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;
}
编译并运行该代码的结果如下:
The minimum is 30
Trace: Inside main function
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++
这是因为预处理器将以下代码:
cout << MKSTR(HELLO C++) << endl;
转化为:
cout << "HELLO C++" << endl;
##
操作符用于连接两个标记。如下所示:
#define CONCAT( x, y ) x ## y
例如,CONCAT(HELLO, C++)
在程序中被替换为"HELLO C++"。
六. 预定义C++宏
C++提供了一些预定义的宏,如下所示:
序号 |
宏名 |
描述 |
1 |
LINE |
包含当前编译时的行号。 |
2 |
FILE |
包含当前编译的文件名。 |
3 |
DATE |
包含源文件编译为目标代码时的日期,格式为月/日/年 。 |
4 |
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