C语言预处理器

news2024/10/5 14:03:35

C 预处理器不是编译器的组成部分,但是它是编译过程中一个单独的步骤。简言之,C 预处理器只不过是一个文本替换工具而已,它们会指示编译器在实际编译之前完成所需的预处理。我们将把 C 预处理器(C Preprocessor)简写为 CPP。

所有的预处理器命令都是以井号(#)开头。它必须是第一个非空字符,为了增强可读性,预处理器指令应从第一列开始。下面列出了所有重要的预处理器指令:

预处理器实例

分析下面的实例来理解不同的指令。

#define MAX_ARRAY_LENGTH 20

这个指令告诉 CPP 把所有的 MAX_ARRAY_LENGTH 定义为 20。使用 #define 定义常量来增强可读性。

#include <stdio.h>
#include "myheader.h"

这些指令告诉 CPP 从系统库中获取 stdio.h,并添加文本到当前的源文件中。下一行告诉 CPP 从本地目录中获取 myheader.h,并添加内容到当前的源文件中。

#undef  FILE_SIZE
#define FILE_SIZE 42

这个指令告诉 CPP 取消已定义的 FILE_SIZE,并定义它为 42。

#ifndef MESSAGE
   #define MESSAGE "You wish!"
#endif

这个指令告诉 CPP 只有当 MESSAGE 未定义时,才定义 MESSAGE。

#ifdef DEBUG
   /* Your debugging statements here */
#endif

这个指令告诉 CPP 如果定义了 DEBUG,则执行处理语句。在编译时,如果您向 gcc 编译器传递了 -DDEBUG 开关量,这个指令就非常有用。它定义了 DEBUG,您可以在编译期间随时开启或关闭调试。

预定义宏

ANSI C 定义了许多宏。在编程中您可以使用这些宏,但是不能直接修改这些预定义的宏。

 让我们来尝试下面的实例:

#include <stdio.h>
 
main()
{
   printf("File :%s\n", __FILE__ );
   printf("Date :%s\n", __DATE__ );
   printf("Time :%s\n", __TIME__ );
   printf("Line :%d\n", __LINE__ );
   printf("ANSI :%d\n", __STDC__ );
 
}

当上面的代码(在文件 test.c 中)被编译和执行时,它会产生下列结果:

File :test.c
Date :Jun 2 2012
Time :03:36:24
Line :8
ANSI :1

预处理器运算符

C 预处理器提供了下列的运算符来帮助您创建宏:

宏延续运算符(\)

一个宏通常写在一个单行上。但是如果宏太长,一个单行容纳不下,则使用宏延续运算符(\)。例如:

#define  message_for(a, b)  \
    printf(#a " and " #b ": We love you!\n")

字符串常量化运算符(#)

在宏定义中,当需要把一个宏的参数转换为字符串常量时,则使用字符串常量化运算符(#)。在宏中使用的该运算符有一个特定的参数或参数列表。例如:

#include <stdio.h>
 
#define  message_for(a, b)  \
    printf(#a " and " #b ": We love you!\n")
 
int main(void)
{
   message_for(Carole, Debra);
   return 0;
}

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

Carole and Debra: We love you!

标记粘贴运算符(##)

宏定义内的标记粘贴运算符(##)会合并两个参数。它允许在宏定义中两个独立的标记被合并为一个标记。例如:

#include <stdio.h>
 
#define tokenpaster(n) printf ("token" #n " = %d", token##n)
 
int main(void)
{
   int token34 = 40;
   
   tokenpaster(34);
   return 0;
}

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

token34 = 40

这是怎么发生的,因为这个实例会从编译器产生下列的实际输出:、

printf ("token34 = %d", token34);

这个实例演示了 token##n 会连接到 token34 中,在这里,我们使用了字符串常量化运算符(#)标记粘贴运算符(##)

defined() 运算符

预处理器 defined 运算符是用在常量表达式中的,用来确定一个标识符是否已经使用 #define 定义过。如果指定的标识符已定义,则值为真(非零)。如果指定的标识符未定义,则值为假(零)。下面的实例演示了 defined() 运算符的用法:

#include <stdio.h>
 
#if !defined (MESSAGE)
   #define MESSAGE "You wish!"
#endif
 
int main(void)
{
   printf("Here is the message: %s\n", MESSAGE);  
   return 0;
}

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

Here is the message: You wish!

参数化的宏

CPP 一个强大的功能是可以使用参数化的宏来模拟函数。例如,下面的代码是计算一个数的平方:

int square(int x) {
   return x * x;
}

我们可以使用宏重写上面的代码,如下:

#define square(x) ((x) * (x))

在使用带有参数的宏之前,必须使用 #define 指令定义。参数列表是括在圆括号内,且必须紧跟在宏名称的后边。宏名称和左圆括号之间不允许有空格。例如:

#include <stdio.h>
 
#define MAX(x,y) ((x) > (y) ? (x) : (y))
 
int main(void)
{
   printf("Max between 20 and 10 is %d\n", MAX(10, 20));  
   return 0;
}

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

Max between 20 and 10 is 20

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/126112.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

pybind11学习 | 使用CMake构建系统并生成pyd文件

文章目录一 通过Visual Studio生成二 通过CMake生成一 通过Visual Studio生成 在我之前的一篇文章pybind11学习 | VS2022下安装配置中&#xff0c;描述了如何通过配置VS2022实现pybind11项目构建和编译成Python拓展模块。 二 通过CMake生成 项目结构如下&#xff1a; 其中py…

(二十七)Vue组件的样式

文章目录scoped属性实现原理lang属性样式穿透Vue学习目录 上一篇&#xff1a;&#xff08;二十六&#xff09;Vue之插件 scoped属性 scoped 属性是 HTML5 中的新属性。如果使用该属性&#xff0c;则样式仅仅应用到 style 元素的父元素及其子元素。即让样式在局部生效&#x…

kafka多线程消费

Kafka consumer 多线程消费 kafka 消费者对象 - KafkaConsumer是非线程安全的。与KafkaProducer不同&#xff0c;KafkaProducer是线程安全的&#xff0c;因为开发者可以在多个线程中放心地使用同一个KafkaProducer实例。 但是对于消费者而言&#xff0c;由于它是非线程安全的…

FreeFileSync 11.29 发布

导读FreeFileSync 是一款开源软件&#xff0c;适用于 Windows、macOS 和 Linux。FreeFileSync 本质是一个用于文件夹对比和同步的软件&#xff0c;它可以创建和管理所有重要文件的备份副本。FreeFileSync 不是每次都复制每个文件&#xff0c;而是确定源文件夹和目标文件夹之间的…

使用 ClusterResourceSet 为 Cluster API 集群自动安装 CNI 插件

1 什么是 Cluster API Cluster API[1] 是一个 Kubernetes 子项目&#xff0c;它将声明式、Kubernetes 风格的 API 引入到集群的创建、配置和管理中。Cluster API 支持在 AWS, Azure, GCP, vSphere, KubeVirt 等多种环境中创建和管理 Kuberenetes 集群&#xff0c;并负责提供部…

单例(Singleton)设计模式

一、单例(Singleton)设计模式说明 设计模式是在大量的实践中总结和理论化之后优选的代码结构、编程风格、以及解决问题的思考方式。设计模式免去我们自己再思考和摸索。就像是经典的棋谱&#xff0c;不同的棋局&#xff0c;我们用不同的棋谱&#xff0c;"套路"所谓类…

WebView以及使用HTTP访问访问网络

文章目录使用网络技术WebView的用法使用HTTP访问网络使用HttpURLConnection使用OkHttp使用网络技术 在Android开发当中,我们应该合理的使用网络编写出更加出色的应用程序,下面学习以下如何在手机端使用HTTP和服务器进行网络交互,并对服务器返回的数据进行解析,这也是在Android…

爽啊,这么多有趣好玩强大的 Python 库

Python语言简洁、易读以及可扩展&#xff0c;在国内外用 Python 做研究的非常多。 Python 语言向来以丰富的第三方库而闻名。这么多有趣好玩且强大&#xff0c;靠一个人去寻找太难了。 最近粉丝群小伙伴们又罗列了一些&#xff0c;分享给大家。喜欢记得点个赞&#xff0c;加入…

OpenHarmony#深入浅出学习eTs#(三)UI布局

本项目Gitee仓地址&#xff1a;深入浅出eTs学习: 带大家深入浅出学习eTs (gitee.com) 一、ArkUI介绍 框架介绍 方舟开发框架&#xff08;简称&#xff1a;ArkUI&#xff09;&#xff0c;是一套UI开发框架&#xff0c;提供开发者进行应用UI开发时所必需的能力。 基本概念 组…

力扣sql入门篇(二)

力扣sql入门篇(二) 1 计算特殊奖金 1.1 题目内容 1.1.1 基本题目信息 1.1.2 示例输入输出 1.2 示例sql语句 SELECT employee_id, case when employee_id%21 AND name not like "M%" then salary else 0 end bonus FROM Employees ORDER BY employee_id;1.3 运行…

【软件测试】测试人的一份“漂亮“的年终总结报告......

目录&#xff1a;导读前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09;前言 不管这一年&#xf…

举一反三-自建zabbix监控mysql

之前写过2篇zabbix监控redis的文章。 本篇针对的是mysql。除了描述如何创建mysql监控的步骤,本篇另一个目的是描述创建任意一个监控对象的基本原理,未来面对其它监控对象时,可以举一反三。 zabbix监控的最基本的部件时zabbix server和zabbix agent. zabbix server负责汇总…

c++primer 第4章 表达式

文章目录第4章 表达式4.1 基础4.1.1 基础概念4.1.2 优先级与结合律4.1.3 求值顺序4.2 算术运算符4.3 逻辑和关系运算符4.4 赋值运算符4.5 递增和递减运算符4.6 成员访问运算符4.7 条件运算符4.8 位运算符4.9 sizeof运算符4.10 逗号运算符4.11 类型转换4.11.1 算术转换4.11.2 其…

ES6-ES11笔记(1)

关于这个视频的笔记 (https://www.bilibili.com/video/BV1uK411H7on?p29&vd_source3cf72bb393b8cc11b96c6d4bfbcbd890) 1.ES6 1.1let的一些注意点 let a; let b,c,d; let e 100; let f"你好",g101;// 变量名不能重复声明 // let testDepulicate 123456 // …

无信息变量消除法研究及实现(Matlab代码实现)

目录 &#x1f4a5;1 概述 &#x1f4da;2 运行结果 &#x1f389;3 参考文献 &#x1f468;‍&#x1f4bb;4 Matlab代码 &#x1f4a5;1 概述 波长变量筛选的方法主要有相关系数法&#xff0c;逐步回归法&#xff0c;无信息变量消除法(UVE)&#xff0c;遗传算法(genetic …

python圣诞树词云

一、前言 圣诞节虽然是西方节日&#xff0c;但是个人还是比较喜欢的&#xff08;没有崇洋媚外的意思&#xff0c;中国的春节也超级棒&#xff09;&#xff0c;一个是圣诞节的氛围&#xff0c;圣诞节的圣诞老人等象征、雪花麋鹿等元素&#xff0c;都充满了浪漫的氛围。我想这也是…

Linux的文件系统编程(1)

What makes the desert beautiful is that somewhere it hides a well. 沙漠之所以美丽,是因为在它的某个角落隐藏着一口井. Linux的文件系统编程&#xff08;1&#xff09;运行过程框架标准IO和文件IO标准IO文件IO(主要学)open函数两个参数三个参数close函数read函数write函数…

Python基础语法(二)

Python基础语法&#xff08;二&#xff09; 函数 编程中的函数和数学中的函数有一定的相似之处. 数学上的函数, 比如 y sin x , x 取不同的值, y 就会得到不同的结果. 编程中的函数, 是一段 可以被重复使用的代码片段 . 代码示例: 求数列的和, 不使用函数 # 1. 求 1 - 100 …

树Tree【代码笔记】

树【Tree】 树是n&#xff08;n>0&#xff09;个结点的有限集。当n 0时&#xff0c;称为空树。在任意一棵非空树中应满足&#xff1a; 有且仅有一个特定的称为根的结点。当n>1时&#xff0c;其余节点可分为m&#xff08;m>0&#xff09;个互不相交的有限集T1,T2,……

OpenHarmony#深入浅出学习eTs#(六)编写eTs第一个控件

本项目Gitee仓地址&#xff1a;深入浅出eTs学习: 带大家深入浅出学习eTs (gitee.com) 一、控件基本属性 在使用第一个控件前&#xff0c;我们需要了解一些控件都有哪些基础属性&#xff0c;比如说我们在Super Visual中使用过的长宽和字体大小等等&#xff0c;通用属性有以下这…