- C++ 基础
- C++ 首页
- C++ 概述
- C++ 环境设置
- C++ 基本语法
- C++ 注释
- C++ Hello World
- C++ 省略命名空间
- C++ 常量/字面量
- C++ 关键字
- C++ 标识符
- C++ 数据类型
- C++ 数值数据类型
- C++ 字符数据类型
- C++ 布尔数据类型
- C++ 变量类型
- C++ 变量作用域
- C++ 多个变量
- C++ 基本输入/输出
- C++ 修饰符类型
- C++ 存储类
- C++ 运算符
- C++ 数字
- C++ 枚举
- C++ 引用
- C++ 日期与时间
- C++ 控制语句
- C++ 决策
- C++ if 语句
- C++ if else 语句
- C++ 嵌套 if 语句
- C++ switch 语句
- C++ 嵌套 switch 语句
- C++ 循环类型
- C++ while 循环
- C++ for 循环
- C++ do while 循环
- C++ foreach 循环
- C++ 嵌套循环
- C++ break 语句
- C++ continue 语句
- C++ goto 语句
- C++ 构造函数
- C++ 构造函数与析构函数
- C++ 复制构造函数
- C++ 文件处理
- C++ 文件和流
- C++ 从文件中读取
C++ 预处理器
预处理器是指令,它们指示编译器在实际编译开始之前预处理信息。
所有预处理器指令都以 # 开头,一行预处理器指令之前只能出现空格字符。预处理器指令不是 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,它将包含大量信息,并且在底部,您会发现值替换如下:
$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 中可用。 # 运算符导致将 replacement-text 令牌转换为用引号括起来的字符串。
考虑以下宏定义:
#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 | __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