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

前言


预处理器

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

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

例如#include <iostream>

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


#define预处理

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

#define PI 3.14159

示例:

#include <iostream>

// 定义常量 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 <iostream>

// 定义带参数的宏
#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 <iostream>

// 定义一个标识符
#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.

上述运行结果:
在这里插入图片描述
如果我们将#define DEBUG_MODE注释掉,就会有
在这里插入图片描述

#ifndef

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

#if、#elif、#else 和 #endif

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

示例:

#include <iostream>

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Sciurdae

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值