文章

C++ 预处理器

C++ 预处理器

预处理器是一些指令,指示编译器在实际编译之前所需完成的预处理。

所有的预处理器指令都是以井号(#)开头,只有空格字符可以出现在预处理指令之前。预处理指令不是 C++ 语句,所以它们不会以分号(;)结尾。

define预处理

#define 预处理指令用于创建符号常量。该符号常量通常称为宏,指令的一般形式是:

1
#define macro-name replacement-text 

当这一行代码出现在一个文件中时,在该文件中后续出现的所有宏都将会在程序编译之前被替换为 replacement-text。

函数宏

您可以使用 #define 来定义一个带有参数的宏,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#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;
}

条件编译

有几个指令可以用来有选择地对部分程序源代码进行编译。这个过程被称为条件编译。

语法:

1
2
3
#ifndef NULL
   #define NULL 0
#endif

#和##运算符

#运算符会把参数转化为字符串,##运算符用于连接两个参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>
using namespace std;

#define MKSTR( x ) #x
#define concat(a, b) a##b

int main ()
{
    int num1 = 100;
    
    cout << MKSTR(HELLO C++) << endl;
    
    cout << concat(num, 1) << endl;

    return 0;
} 

运行结果

1
2
HELLO C++
100
  • 在一个宏中的参数前面使用一个#,预处理器会把这个参数转换为一个字符数组,当传入参数之间存在空格时,编译器会自动连接各个子字符串,在每个字符串之间以一个空格连接,并忽略剩余空格

  • ##是一种分隔连接方式,它的作用是先分割,然后进行强制连接,将宏定义的多个形参转换成一个实际参数名

    1. 当用##连接形参时,##前后的空格可有可无
    2. 连接后的实际参数名,必须为实际存在的参数名或是编译器已知的宏定义
    3. 如果##后的参数本身也是一个宏的话,##会阻止这个宏的展开

预定义宏

描述
__DATE__当前日期,一个以 “MMM DD YYYY” 格式表示的字符常量。
__TIME__当前时间,一个以 “HH:MM:SS” 格式表示的字符常量。
__FILE__这会包含当前文件名,一个字符串常量。
__LINE__这会包含当前行号,一个十进制常量。
本文由作者按照 CC BY 4.0 进行授权