Appearance
C++ 预处理器
预处理器是 C++ 编译过程的第一步,它在实际编译之前处理源代码。预处理器指令以#开头,用于包含文件、定义宏、条件编译等。
1. 预处理器的基本概念
预处理器指令在编译之前被处理,它们不是 C++ 语句,不需要以分号结尾。
1.1 常用的预处理器指令
| 指令 | 描述 |
|---|---|
#include | 包含头文件 |
#define | 定义宏 |
#undef | 取消宏定义 |
#ifdef | 如果宏已定义 |
#ifndef | 如果宏未定义 |
#if | 如果条件为真 |
#else | 否则 |
#elif | 否则如果 |
#endif | 结束条件编译 |
#line | 设置行号 |
#error | 生成错误信息 |
#pragma | 编译器特定指令 |
2. #include 指令
2.1 包含系统头文件
cpp
#include <iostream>
#include <vector>
#include <string>
int main() {
std::cout << "Hello, World!" << std::endl;
return 0;
}2.2 包含用户头文件
cpp
#include "myheader.h"
int main() {
return 0;
}3. #define 指令
3.1 定义常量
cpp
#include <iostream>
#define PI 3.14159
#define MAX_SIZE 100
int main() {
std::cout << "PI = " << PI << std::endl;
std::cout << "MAX_SIZE = " << MAX_SIZE << std::endl;
return 0;
}3.2 定义宏函数
cpp
#include <iostream>
#define SQUARE(x) ((x) * (x))
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#define MIN(a, b) ((a) < (b) ? (a) : (b))
int main() {
std::cout << "SQUARE(5) = " << SQUARE(5) << std::endl;
std::cout << "MAX(10, 20) = " << MAX(10, 20) << std::endl;
std::cout << "MIN(10, 20) = " << MIN(10, 20) << std::endl;
return 0;
}3.3 宏的注意事项
cpp
#include <iostream>
#define SQUARE(x) ((x) * (x))
int main() {
int a = 5;
std::cout << "SQUARE(a++) = " << SQUARE(a++) << std::endl;
std::cout << "a = " << a << std::endl;
return 0;
}4. 条件编译
4.1 #ifdef 和 #ifndef
cpp
#include <iostream>
#define DEBUG
int main() {
#ifdef DEBUG
std::cout << "调试模式" << std::endl;
#else
std::cout << "发布模式" << std::endl;
#endif
return 0;
}4.2 #if、#elif、#else
cpp
#include <iostream>
#define VERSION 2
int main() {
#if VERSION == 1
std::cout << "版本 1" << std::endl;
#elif VERSION == 2
std::cout << "版本 2" << std::endl;
#else
std::cout << "其他版本" << std::endl;
#endif
return 0;
}4.3 防止头文件重复包含
cpp
#ifndef MYHEADER_H
#define MYHEADER_H
void func();
#endif或者使用#pragma once:
cpp
#pragma once
void func();5. #undef 指令
cpp
#include <iostream>
#define PI 3.14159
int main() {
std::cout << "PI = " << PI << std::endl;
#undef PI
#ifdef PI
std::cout << "PI 已定义" << std::endl;
#else
std::cout << "PI 未定义" << std::endl;
#endif
return 0;
}6. #line 指令
cpp
#include <iostream>
int main() {
std::cout << "当前行号: " << __LINE__ << std::endl;
#line 100
std::cout << "当前行号: " << __LINE__ << std::endl;
return 0;
}7. #error 指令
cpp
#include <iostream>
#define VERSION 1
#if VERSION < 2
#error "版本必须大于或等于 2"
#endif
int main() {
return 0;
}8. #pragma 指令
8.1 #pragma once
cpp
#pragma once
void func();8.2 #pragma message
cpp
#include <iostream>
#pragma message("编译中...")
int main() {
return 0;
}8.3 #pragma warning
cpp
#include <iostream>
#pragma warning(disable: 4996)
int main() {
return 0;
}9. 预定义宏
C++ 预处理器提供了一些预定义的宏:
| 宏 | 描述 |
|---|---|
__LINE__ | 当前行号 |
__FILE__ | 当前文件名 |
__DATE__ | 当前日期 |
__TIME__ | 当前时间 |
__STDC__ | 如果编译器遵循 ANSI C,则为 1 |
__cplusplus | 如果是 C++ 编译器,则定义 |
示例
cpp
#include <iostream>
int main() {
std::cout << "当前行号: " << __LINE__ << std::endl;
std::cout << "当前文件: " << __FILE__ << std::endl;
std::cout << "当前日期: " << __DATE__ << std::endl;
std::cout << "当前时间: " << __TIME__ << std::endl;
std::cout << "C++ 版本: " << __cplusplus << std::endl;
return 0;
}10. 示例:综合运用
现在,让我们看一个综合运用各种预处理器特性的例子:
cpp
#include <iostream>
#include <vector>
#define DEBUG
#define VERSION 2
#define MAX_SIZE 100
#define SQUARE(x) ((x) * (x))
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#define MIN(a, b) ((a) < (b) ? (a) : (b))
void debug_print(const std::string& message) {
#ifdef DEBUG
std::cout << "[DEBUG] " << message << std::endl;
#endif
}
int main() {
// 预定义宏
std::cout << "预定义宏:" << std::endl;
std::cout << "当前行号: " << __LINE__ << std::endl;
std::cout << "当前文件: " << __FILE__ << std::endl;
std::cout << "当前日期: " << __DATE__ << std::endl;
std::cout << "当前时间: " << __TIME__ << std::endl;
std::cout << "C++ 版本: " << __cplusplus << std::endl;
std::cout << std::endl;
// 宏常量
std::cout << "宏常量:" << std::endl;
std::cout << "MAX_SIZE = " << MAX_SIZE << std::endl;
std::cout << std::endl;
// 宏函数
std::cout << "宏函数:" << std::endl;
std::cout << "SQUARE(5) = " << SQUARE(5) << std::endl;
std::cout << "MAX(10, 20) = " << MAX(10, 20) << std::endl;
std::cout << "MIN(10, 20) = " << MIN(10, 20) << std::endl;
std::cout << std::endl;
// 条件编译
std::cout << "条件编译:" << std::endl;
#if VERSION == 1
std::cout << "版本 1" << std::endl;
#elif VERSION == 2
std::cout << "版本 2" << std::endl;
#else
std::cout << "其他版本" << std::endl;
#endif
std::cout << std::endl;
// 调试输出
std::cout << "调试输出:" << std::endl;
debug_print("程序开始运行");
std::vector<int> vec = {1, 2, 3, 4, 5};
for (int x : vec) {
debug_print("处理元素: " + std::to_string(x));
}
debug_print("程序结束运行");
return 0;
}小结
C++ 预处理器包括:
预处理器的基本概念:
- 预处理器指令以
#开头 - 在实际编译之前处理源代码
- 预处理器指令以
#include 指令:
- 包含系统头文件:
#include <iostream> - 包含用户头文件:
#include "myheader.h"
- 包含系统头文件:
#define 指令:
- 定义常量:
#define PI 3.14159 - 定义宏函数:
#define SQUARE(x) ((x) * (x))
- 定义常量:
条件编译:
#ifdef:如果宏已定义#ifndef:如果宏未定义#if:如果条件为真#elif:否则如果#else:否则#endif:结束条件编译
#undef 指令:
- 取消宏定义:
#undef PI
- 取消宏定义:
#line 指令:
- 设置行号:
#line 100
- 设置行号:
#error 指令:
- 生成错误信息:
#error "错误信息"
- 生成错误信息:
#pragma 指令:
#pragma once:防止头文件重复包含#pragma message:输出编译信息#pragma warning:控制警告
预定义宏:
__LINE__:当前行号__FILE__:当前文件名__DATE__:当前日期__TIME__:当前时间__cplusplus:C++ 版本
关键概念:
- 预处理器:在编译之前处理源代码
- #include:包含头文件
- #define:定义宏
- 条件编译:根据条件编译不同的代码
- 预定义宏:预处理器提供的宏
- 宏函数:使用宏定义的函数
掌握预处理器是编写可移植和可配置 C++ 程序的重要基础,在后续章节中,我们将学习 C++ 的信号处理。