Skip to content

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++ 预处理器包括:

  1. 预处理器的基本概念

    • 预处理器指令以#开头
    • 在实际编译之前处理源代码
  2. #include 指令

    • 包含系统头文件:#include <iostream>
    • 包含用户头文件:#include "myheader.h"
  3. #define 指令

    • 定义常量:#define PI 3.14159
    • 定义宏函数:#define SQUARE(x) ((x) * (x))
  4. 条件编译

    • #ifdef:如果宏已定义
    • #ifndef:如果宏未定义
    • #if:如果条件为真
    • #elif:否则如果
    • #else:否则
    • #endif:结束条件编译
  5. #undef 指令

    • 取消宏定义:#undef PI
  6. #line 指令

    • 设置行号:#line 100
  7. #error 指令

    • 生成错误信息:#error "错误信息"
  8. #pragma 指令

    • #pragma once:防止头文件重复包含
    • #pragma message:输出编译信息
    • #pragma warning:控制警告
  9. 预定义宏

    • __LINE__:当前行号
    • __FILE__:当前文件名
    • __DATE__:当前日期
    • __TIME__:当前时间
    • __cplusplus:C++ 版本

关键概念:

  • 预处理器:在编译之前处理源代码
  • #include:包含头文件
  • #define:定义宏
  • 条件编译:根据条件编译不同的代码
  • 预定义宏:预处理器提供的宏
  • 宏函数:使用宏定义的函数

掌握预处理器是编写可移植和可配置 C++ 程序的重要基础,在后续章节中,我们将学习 C++ 的信号处理。