当前位置: 首页 > 文档资料 > C++ 中文教程 >

C++ Preprocessor

优质
小牛编辑
134浏览
2023-12-01

预处理器是指令,它指示编译器在实际编译开始之前预处理信息。

所有预处理程序指令都以#开头,并且只有空格字符可能出现在一行上的预处理程序指令之前。 预处理程序指令不是C ++语句,因此它们不以分号(;)结尾。

您已经在所有示例中看到了#include指令。 此宏用于将头文件包含到源文件中。

C ++支持许多预处理程序指令,如#include,#define,#if,#else,#line等。让我们看看重要的指令 -

#define预处理器 (The #define Preprocessor)

#define预处理程序指令创建符号常量。 符号常量称为macro ,指令的一般形式是 -

#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,它将有很多信息,在底部,你会发现更换的值如下 -

$gcc -E test.cpp > test.p
...
int main () {
   cout << "Value of PI :" << 3.14159 << endl; 
   return 0;
}

Function-Like Macros

您可以使用#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 statment注释掉程序的一部分,如下所示 -

#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 ++提供了下面提到的许多预定义宏 -

Sr.No宏观和描述
1

__LINE__

它包含编译时程序的当前行号。

2

__FILE__

它包含编译时程序的当前文件名。

3

__DATE__

它包含一个月/日/年形式的字符串,它是将源文件转换为目标代码的日期。

4

__TIME__

它包含一个形式为hour:minute:second的字符串,它是编译程序的时间。

让我们看一下上述所有宏的示例 -

#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