Advertisement

什么?你还不知道什么是C++ 预处理器?看这一篇就够了~

阅读量:

目录

C++ 预处理器

#define 预处理

参数宏

条件编译

和 ## 运算符

C++ 中的预定义宏

最后知识点

写在最后


C++ 预处理器

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

所有预处理指令都以井号符号(#)开头,并且在执行这些操作时仅允许前后出现空格字符。这些指令并非典型的C++语句类型,并因此不会被标记为需要结束于分号符号(;)。

我们观察到,在各个实例中都包含了 #include 指令。这个宏的作用是将头文件导入到源文件中。

除了C++的标准库之外,它还提供了一系列强大的预处理功能。以下是一些常见的预处理指令:像 #include 用于包含头文件、#define 用于宏定义、#if 用于条件编译等。我们一起来了解一下这些关键工具的用法吧!

#define 预处理

#define 预处理指令的作用是负责创建符号常量,并在编程环境中扮演重要角色。所使用的符号常量通常被称为 ,在编程中被广泛使用,并且具有特定的表示形式。

复制代码

每当某个特定的代码行包含在一个文件中时,在编译阶段之前,该文件中的所有宏都会被替换成指定的 text。例如

复制代码
 #include <iostream>

    
 using namespace std;
    
  
    
 #define PI 3.14159
    
  
    
 int main ()
    
 {
    
  
    
     cout << "Value of PI :" << PI << endl; 
    
  
    
     return 0;
    
 }
    
    
    
    
    AI助手

请我们现在对这段代码进行测试以观察预处理后的结果 假设源代码文件已存在 我们将使用 -E 选项来进行编译 并将其输出重定向至test.p文件中 一旦查看test.p文件内容时 您将发现它已经包含大量详细信息 并且在尾部部分的数值已经被修改为以下内容:

复制代码
 ...

    
 int main ()
    
 {
    
  
    
     cout << "Value of PI :" << 3.14159 << endl; 
    
  
    
     return 0;
    
 }
    
    
    
    
    AI助手

参数宏

您可以使用 #define 来定义一个带有参数的宏,如下所示:

复制代码
 #include <iostream>

    
 using namespace std;
    
  
    
 #define MIN(a,b) (a<b ? a : b)
    
  
    
 int main ()
    
 {
    
    int i, j;
    
    i = 100;
    
    j = 30;
    
    cout <<"较小的值为:" << MIN(i, j) << endl;
    
  
    
     return 0;
    
 }
    
    
    
    
    AI助手

当上面的代码被编译和执行时,它会产生下列结果:

复制代码

条件编译

存在一组指令能够根据特定条件选择性地处理部分代码块。
这一技术被称作条件编译。

条件预处理器的结构与 if 选择结构很像。请看下面这段预处理器的代码:

复制代码

您可以只在调试时进行编译,调试开关可以使用一个宏来实现,如下所示:

复制代码

当指令 #ifdef DEBUG 在执行前已经定义了符号常量 DEBUG时,则会触发对程序中 cerr 的编译操作。采用 #if 0 语句来注释掉程序的一部分,请参考以下示例:

复制代码

让我们尝试下面的实例:

复制代码
 #include <iostream>

    
 using namespace std;
    
 #define DEBUG
    
  
    
 #define MIN(a,b) (((a)<(b)) ? a : b)
    
  
    
 int main ()
    
 {
    
    int i, j;
    
    i = 100;
    
    j = 30;
    
 #ifdef DEBUG
    
    cerr <<"Trace: Inside main function" << endl;
    
 #endif
    
  
    
 #if 0
    
    cout << MKSTR(HELLO C++) << endl;
    
 #endif
    
  
    
    cout <<"The minimum is " << MIN(i, j) << endl;
    
  
    
 #ifdef DEBUG
    
    cerr <<"Trace: Coming out of main function" << endl;
    
 #endif
    
     return 0;
    
 }
    
    
    
    
    AI助手

当上面的代码被编译和执行时,它会产生下列结果:

复制代码

# 和 ## 运算符

和 ## 预处理运算符在C++语言及ANSI/ISO C标准中均为可应用的工具。它们负责将 replacement-text 标识符转换成带引号的字符串形式。

请看下面的宏定义:

复制代码
 #include <iostream>

    
 using namespace std;
    
  
    
 #define MKSTR( x ) #x
    
  
    
 int main ()
    
 {
    
     cout << MKSTR(HELLO C++) << endl;
    
  
    
     return 0;
    
 }
    
    
    
    
    AI助手

当上面的代码被编译和执行时,它会产生下列结果:

复制代码

让我们来看看它是如何工作的。不难理解,C++ 预处理器把下面这行:

复制代码

转换成了:

复制代码

运算符用于连接两个令牌。下面是一个实例:

复制代码

在程序运行过程中,当出现CONCAT指令时,在某些编程环境中(如QBASIC),它会将给定的参数连接起来,并将这些连接后的结果用于替代宏变量或直接生成字符串。比如,在程序中使用CONCAT(HELLO, C++)会替换成字符串'HELLO C++'。如以下示例所示:

复制代码
 #include <iostream>

    
 using namespace std;
    
  
    
 #define concat(a, b) a ## b
    
 int main()
    
 {
    
    int xy = 100;
    
    
    
    cout << concat(x, y);
    
    return 0;
    
 }
    
    
    
    
    AI助手

当上面的代码被编译和执行时,它会产生下列结果:

复制代码

让我们来看看它是如何工作的。不难理解,C++ 预处理器把下面这行:

复制代码

转换成了:

复制代码

C++ 中的预定义宏

C++ 提供了下表所示的一些预定义宏:

描述
LINE 这会在程序编译时包含当前行号。
FILE 这会在程序编译时包含当前文件名。
DATE 这会包含一个形式为 month/day/year 的字符串,它表示把源文件转换为目标代码的日期。
TIME 这会包含一个形式为 hour:minute:second 的字符串,它表示程序被编译的时间。

让我们看看上述这些宏的实例:

复制代码
>       1. #include <iostream>

>  
>       2. using namespace std;
>  
>       3.  
>  
>       4. int main ()
>  
>       5. {
>  
>       6.     cout << "Value of __LINE__ : " << __LINE__ << endl;
>  
>       7.     cout << "Value of __FILE__ : " << __FILE__ << endl;
>  
>       8.     cout << "Value of __DATE__ : " << __DATE__ << endl;
>  
>       9.     cout << "Value of __TIME__ : " << __TIME__ << endl;
>  
>       10.  
>  
>       11.     return 0;
>  
>       12. }
>  
>  
>  
>  
>     AI助手

当上面的代码被编译和执行时,它会产生下列结果:

复制代码

最后知识点

### 运算符

在字符串化处理中使用#符号,在宏定义中将后续参数转换为字符串。

在作为字符串化操作使用时,
其主要功能是将宏参数直接转换为不进行扩展的字符串常量。

宏定义参数左右两边的空格会被忽略,
各个 Token 之间的多个空格会被转换成一个空格。
含有特殊含义字符如'或\时,
这些字符前面会自动被添加上转义字符 \。

连接符号,把参数连在一起。

将多个 Token 连接成一个 Token。要点:

  • 它不能是宏定义中的第一个或最后一个 Token。
  • 前后的空格可有可无。

该文档详细阐述了各种基本数据类型及其对应用途,并明确了变量在程序中的声明与赋初过程。涵盖整数类型、浮点数类型、字符类型以及指针类型的定义;同时涉及变量声明与初始化的过程。这些内容为后续算法实现奠定了必要的基础条件。

该段文字已经按照要求进行了改写

控制语句 包括条件语句、循环语句、跳转语句等。

函数及其参数的传递机制 包括以下几方面:首先涉及函数的定义域与值域;其次探讨具体输入输出变量之间的关系;最后详细阐述参数的具体传输途径以及具体的实现手段。特别地,在这一过程中具体包括参数的接收与发送机制以及相应的处理逻辑。值得注意的是,在数据处理过程中具体采用的方式包括但不限于:基于值的数据传输与基于指针的数据传输策略。

数组与指针涉及的内容包括:对数组的定义说明、对数组元素的操作处理、高维(多维)数组的概念及其特点、对指针进行的操作运算等详细说明。

字符串处理 包括字符串的定义、字符串常见操作(比较、复制、连接、分割等)。

文件操作 包括文件打开、读取、写入、关闭等常用操作。

内存管理 包括动态内存分配函数malloc和free的使用。

写在最后

最近流量越来越少,求求大家给个关注,收藏呗,谢谢啦

全部评论 (0)

还没有任何评论哟~