C++学习贴---C++预处理器

文章目录

  • 前言
  • 预处理器
    • #define预处理
    • 条件编译
      • #ifdef
      • #ifndef
      • #if、#elif、#else 和 #endif
    • #和##运算符
  • 预定义宏

前言


预处理器

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

预处理器负责处理以**井号(#)**开头的预处理指令,这些指令在编译过程之前对源代码进行一些文本替换和操作。

例如#include 

除此之外,还有#define、#if、#else、#line 等


#define预处理

#define: 用于定义宏,将一个标识符替换为特定的文本。宏在代码中可以起到类似函数的作用,但是是在编译时进行文本替换的。

#define PI 3.14159

示例:

#include 

// 定义常量 PI
#define PI 3.14159

int main() {
    // 使用定义的常量 PI
    double radius = 5.0;
    double area = PI * radius * radius;

    // 输出计算结果
    std::cout << "半径为 " << radius << " 的圆的面积是: " << area << std::endl;

    return 0;
}

在上述中,用了#define PI 3.14159 这样预处理器会将所有出现的PI替换成3.14159,实际上,编译器处理的代码应该是:

double area = 3.4159  * radius * radius;

除了用#define定义常量的宏之外,还可以定义带有参数的宏;

如:

#include 

// 定义带参数的宏
#define MAX(x, y) ((x) > (y) ? (x) : (y))

int main() {
    int a = 10, b = 7;

    // 使用定义的宏
    int result = MAX(a, b);

    // 输出计算结果
    std::cout << "较大的数是: " << result << std::endl;

    return 0;
}

在实际编译时,预处理器会将所有的MAX(a, b)替换为((a) > (b) ? (a) : (b)),从而实现参数的替换和宏的展开。


条件编译

条件编译: 使用#if、#ifdef、#ifndef、#elif、#else和#endif等指令来根据条件选择性地包含或排除代码块。

#ifdef

#ifdef 是一个预处理器指令,用于在编译时检查一个标识符是否已经被定义。如果指定的标识符已经定义,则预处理器会包含后续的代码块,否则会忽略这个代码块。

使用示例:

#include 

// 定义一个标识符
#define DEBUG_MODE

int main() {
    // 检查标识符是否已经定义
    #ifdef DEBUG_MODE
        std::cout << "Debug mode is enabled." << std::endl;
    #else
        std::cout << "Debug mode is disabled." << std::endl;
    #endif

    return 0;
}

在上述中使用了#define DEBUG_MODE 预定义了一个标识符,后面在main函数中,通过#ifdef DEBUG_MODE来检查。如果存在就会打印Debug mode is enabled.

上述运行结果:
C++学习贴---C++预处理器_第1张图片
如果我们将#define DEBUG_MODE注释掉,就会有
C++学习贴---C++预处理器_第2张图片

#ifndef

这个和#ifdef正好是相反的结果,即如果给定的标识符尚未被定义,则包括代码块。

#if、#elif、#else 和 #endif

这些预处理器指令允许根据条件选择性地包括或排除代码块。

示例:

#include 

#define DEBUG_LEVEL 2

int main() {
    #if DEBUG_LEVEL == 0
        std::cout << "No debugging." << std::endl;
    #elif DEBUG_LEVEL == 1
        std::cout << "Basic debugging." << std::endl;
    #elif DEBUG_LEVEL == 2
        std::cout << "Advanced debugging." << std::endl;
    #else
        std::cout << "Unknown debugging level." << std::endl;
    #endif

    return 0;
}


#和##运算符

#和 ## 是两个特殊的运算符,用于在宏定义中进行字符串化和连接操作。

#运算符(字符串化操作符): 在宏定义中,# 运算符可以将参数转换为字符串常量。在宏的定义中,将参数用 # 运算符括起来,预处理器会将参数的文本形式转换为字符串。

示例:

#define STRINGIZE(x) #x

int main() {
    int value = 42;
    const char* str = STRINGIZE(value);
    // 在这里,str 的值为 "value"
    return 0;
}

STRINGIZE(value) 会被替换为 “value”,因为 #x 将参数 x 转换为字符串。

##运算符(连接操作符): 在宏定义中,## 运算符用于将两个标识符连接在一起,形成一个新的标识符。

#define CONCAT(a, b) a##b

int main() {
    int xy = 42;
    // 在这里,CONCAT(x, y) 会被替换为 xy
    return 0;
}

在上述代码中,CONCAT(x, y) 会被替换为 xy,因为 a##b 将两个参数 a 和 b 连接在一起。


预定义宏

C++ 中有一些预定义的宏,它们由编译器提供,并可在程序中直接使用。这些宏通常用于提供有关编译环境和代码特性的信息。

例如:

  • __cplusplus: 这个宏用于指示 C++ 的版本。如果程序是在 C++ 编译器中编译的,__cplusplus 的值会被设置为一个表示 C++ 版本的整数。
  • FILE: 这个宏会被替换为当前源文件的文件名。
  • LINE: 这个宏会被替换为当前源文件中的行号。
  • funcFUNCTION: 这个宏会被替换为当前函数的名称。
  • DATETIME: 这两个宏会被替换为程序被编译时的日期和时间。

简短的示例:

#include 
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

你可能感兴趣的:(C++学习,c++,学习,开发语言)