C++ 预处理器
预处理器是指令,它向编译器发出指令,在实际编译开始之前对信息进行预处理。
所有预处理器指令都以 # 开头,并且一行中的预处理器指令之前只能出现空白字符。预处理器指令不是 C++ 语句,因此它们不以分号 (;) 结尾。
您已经在所有示例中看到了#include指令。该宏用于将头文件包含到源文件中。
C++ 支持许多预处理器指令,如 #include、#define、#if、#else、#line 等。让我们看看重要的指令 -
#define 预处理器
#define 预处理器指令创建符号常量。符号常量称为宏,指令的一般形式是 -
#define macro-name 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,它将包含大量信息,并且在底部,您会发现替换的值如下 -
$gcc -E test.cpp > 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
如果在指令 #ifdef DEBUG 之前定义了符号常量 DEBUG,则这会导致在程序中编译cerr语句。您可以使用 #if 0 语句注释掉程序的一部分,如下所示 -
#if 0 code prevented from compiling #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 /* This is commented part */ 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++
让我们看看它是如何工作的。很容易理解,C++ 预处理器会改变这条线 -
cout << MKSTR(HELLO C++) << endl;
上面的行将变成下面的行 -
cout << "HELLO C++" << endl;
## 运算符用于连接两个标记。这是一个例子 -
#define CONCAT( x, y ) x ## y
当 CONCAT 出现在程序中时,它的参数被连接起来并用来替换宏。例如,程序中将 CONCAT(HELLO, C++) 替换为“HELLO C++”,如下所示。
#include <iostream> using namespace std; #define concat(a, b) a ## b int main() { int xy = 100; cout << concat(x, y); return 0; }
如果我们编译并运行上面的代码,将产生以下结果 -
100
让我们看看它是如何工作的。很容易理解 C++ 预处理器的转换 -
cout << concat(x, y);
上面的行将被转换为下面的行 -
cout << xy;
预定义的 C++ 宏
C++ 提供了许多下面提到的预定义宏 -
先生编号 | 宏及描述 |
---|---|
1 | __线__ 它包含程序编译时的当前行号。 |
2 | __文件__ 它包含程序编译时的当前文件名。 |
3 | __日期__ 它包含月/日/年形式的字符串,是将源文件转换为目标代码的日期。 |
4 | __时间__ 它包含一个小时:分钟:秒形式的字符串,它是程序编译的时间。 |
让我们看一下上述所有宏的示例 -
#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