C_Cpp_Preprocessing

C/C++ 预处理指令

1. 文件包含

在C/C++中,#include指令用于包含头文件。根据文件名的不同引用方式,有两种形式:

  • #include "filename":首先在源文件所在的目录中查找文件。如果找不到,再在系统默认的目录中查找。
  • #include <filename>:直接从系统默认的目录中查找文件。

示例代码:

// myheader.h
#ifndef MYHEADER_H
#define MYHEADER_H

void sayHello();

#endif // MYHEADER_H

// myheader.cpp
#include "myheader.h"
#include <iostream>

void sayHello() {
    std::cout << "Hello, World!" << std::endl;
}

// main.cpp
#include "myheader.h"

int main() {
    sayHello();
    return 0;
}

在上述代码中,myheader.hmyheader.cpp 包含了函数的声明和定义,而 main.cpp 包含了头文件 myheader.h 并调用了 sayHello 函数。

2. 宏替换

宏定义用于替换代码中的文本片段。在宏定义中,有一些细节需要注意:

2.1 宏定义末尾不加分号

如果在宏定义的末尾加上分号,宏替换时会引入多余的分号。

示例代码:

#define MAX(a, b) ((a) > (b) ? (a) : (b))

int main() {
    int x = 5, y = 10;
    int maxVal = MAX(x, y); // 这里不能加分号
    printf("Max value: %d\n", maxVal);
    return 0;
}

在上面的代码中,MAX 宏用于计算两个数的最大值。

2.2 宏替换中的运算符优先级

在宏定义中,确保使用括号以避免运算符优先级问题。

示例代码:

#define A (2+2)
#define B (3+3)
#define C (A*B)

int main() {
    printf("%d\n", C); // 结果是 (2+2)*(3+3) = 4*6 = 24
    return 0;
}

在上述代码中,使用括号确保了运算顺序正确。

2.3 带有副作用的宏参数

宏参数可能会引起副作用,如 x++ 会改变 x 的值。

示例代码:

#define INCREMENT(x) ((x) + 1)

int main() {
    int a = 5;
    int b = INCREMENT(a++); // 结果是 ((5++) + 1) = 6
    printf("a: %d, b: %d\n", a, b); // 输出 a: 6, b: 6
    return 0;
}

在上述代码中,a 的值在宏替换中被改变。

3. 预定义符号

C/C++ 中有一些预定义符号可以在编译时获取文件名、行号、编译日期和时间等信息。

示例代码:

#include <stdio.h>

int main() {
    printf("File: %s\n", __FILE__);
    printf("Line: %d\n", __LINE__);
    printf("Date: %s\n", __DATE__);
    printf("Time: %s\n", __TIME__);
    return 0;
}

在上述代码中,预定义符号用于打印当前文件名、行号、编译日期和时间。

4. ###

4.1 # 符号

# 符号用于将宏参数转化为字符串。

示例代码:

#define TO_STRING(x) #x

int main() {
    printf("String: %s\n", TO_STRING(Hello, World!)); // 输出 "Hello, World!"
    return 0;
}

在上述代码中,TO_STRING 宏将参数转化为字符串。

4.2 ## 运算符

## 运算符用于连接两个宏参数。

示例代码:

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

int main() {
    int xy = 100;
    printf("Value: %d\n", CONCAT(x, y)); // 输出 100
    return 0;
}

在上述代码中,CONCAT 宏将参数连接成一个标识符。

5. 其他指令

5.1 #ifdef#ifndef

这两个指令用于条件编译,#ifdef 判断某个宏是否被定义,#ifndef 判断某个宏是否未被定义。

示例代码:

#define DEBUG

int main() {
#ifdef DEBUG
    printf("Debug mode\n");
#else
    printf("Release mode\n");
#endif
    return 0;
}

在上述代码中,根据是否定义了 DEBUG 宏,选择编译不同的代码段。

5.2 #if#endif

#if 指令用于更复杂的条件编译,可以进行算术和逻辑运算。

示例代码:

#define VERSION 2

int main() {
#if VERSION == 1
    printf("Version 1\n");
#elif VERSION == 2
    printf("Version 2\n");
#else
    printf("Unknown version\n");
#endif
    return 0;
}

在上述代码中,根据 VERSION 宏的值选择编译不同的代码段。

5.3 #undef

#undef 用于取消宏定义。

示例代码:

#define TEMP 100

int main() {
    printf("TEMP: %d\n", TEMP);
#undef TEMP
    // printf("TEMP: %d\n", TEMP); // 这行会报错,因为 TEMP 已经被取消定义
    return 0;
}

在上述代码中,TEMP 宏在 #undef 指令之后被取消定义,后续无法再使用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值