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

如果已定义符号常量DEBUG,则会导致 cerr 语句在程序中编译在指令#ifdef DEBUG之前.您可以使用#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 __

这包含一个字符串形式的小时:分钟:秒,即程序的时间编译.

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

#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