当前位置: 首页 > article >正文

【C语言】预处理(下)(C语言完结篇)

一、#和##

1、#运算符

这里的#是一个运算符,整个运算符会将宏的参数转换为字符串字面量,它仅可以出现在带参数的宏的替换列表中,我们可以将其理解为字符串化。

我们先看下面的一段代码:

第二个printf中是由两个字符串组成的,这样写法的输出和第一个写法输出是否会有不同呢?

运行结果:
 

可以看到,这两个挨在一块的字符串会被合并起来输出。 

下面我们通过一个例子来弄清楚# 符号到底是怎么个事:

我们现在想在屏幕上打印the value of a is 20 。那么我们可以如下面一样操作:

但是当我们需要对其他几个变量也打印这样的信息呢?那么是不是要重复的写这么一长串的代码,有没有什么办法可以将其简化?

此时我们可以通过宏来解决这个问题,在上面的字符串中,不同的变量发生变化的有三个地方:

一个就是of后面的,这个地方是要填入的是变量名,然后是占位符,然后就是参数了。

参数是比较好解决的,主要是变量名和占位符,这是因为这两个都是字符串,所以我们在使用宏替换的时候,是不会将其替换的,此时是不是就没办法了呢?

对于占位符的替换,我们可以用上面那个代码的情况,两个字符串是可以合并的。

还有就是对于变量名,其就需要使用到我们的#运算符了,我们上面提到了其可以将我们后面的内容字符串化。

代码如下:

 ​​​​

我们看看其运行结果:

可以看到其完美的实现了我们需要的功能。 


2、##运算符

##运算符又是一个完全陌生的符号,其作用是将其两边的符号合成一个符号,其运算宏定义从分离的文本片段创建标识符。##被称为记号粘合运算符。

比如我们现在有一个变量class115,那么我们可以通过粘合class和115来得到它

如下:

我们将其合并后,那么其此时就可以表示我们的变量了,那么我们使用printf将其打印出来,看看是不是10。

如下:

可以看到其可以顺利得到我们的这个变量名字。

下面我们再通过一个例子理解这个运算符:

我们前面使用函数写过一个比较两个数的大小,当我们比较的两个数是整数的时候,那我们就需要写一个整型数据求最大值的函数,当要求浮点数的时候,就需要写一个浮点数使用的函数,但是我们可以知道的是,这两个函数除了返回值类型,和参数的数据类型不一样罢了,其他的都是一样的。

如下:

下面我们通过宏来定义:

这个宏要实现的功能就是根据我们传入的数据类型,然后生成对应的求最大值的函数。

那么主要是解决对于数据类型如何与函数名相连了,那么刚刚好可以使用##进行粘合。

这些函数的名字的共同点如:数据类型_max。

如下:

上面就是我们创建的对于不同的数据类型都可以使用的求最大值的宏,我们根据用户传入的type来确定函数的名字和函数的返回值类型,然后\是一个换行符号。

这里我们使用了##运算符将type与_max连接起来,可以让用户传入的type可以完美的替换。

那么我们就可以通过这个宏来创建需要使用到的求最大值的函数:

运行结果:

二、预处理指令#under 

#under指令的作用是移除一个#define的定义,其语法如下:

其中NAME就是我们要移除的#define定义的名字了,当我们需要使用这个名字重新定义一个宏的时候,那么我们就需要使用#under将其原来的定义移除,然后才可以使用这个名字进行定义一个新的宏。

如下:

上面我们首先使用#define将N定义为100,然后将其在屏幕上打印,然后我们使用#undef先将其原来的定义移除,然后再将N重新定义为hehe字符串,然后将其在屏幕上打印。

 

三、条件编译 

条件编译,类似于我们的选择语句,不过这个过程是在预处理阶段进行的,它会根据我们的条件来决定是否对某些语句进行编译。

1、单分支条件翻译

单分支条件编译就是说我们只有一条分支需要进行判断。

其语法如下:

 可以发现其和if语句类似,也是有个条件表达式决定其里面的内容编译不编译,不过其比if语句多了一个结束的标志。

不过条件表达式其要求的是常量表达式,下面我们使用其看看效果:

那么这个代码就啥都不会打印。因为常量表达式的值是为假的。

那么为什么后面只能为常量表达式呢?这是因为在这个阶段是预处理阶段,在这个阶段,变量还不存在,那么也就不能使用变量了,只能使用常量

2、多分支条件编译 

多分支编译和单分支编译的原理大致相同,不过其就是多了几个选择这样。

其语法如下:

这个就是我们的多分支条件编译的语法,其用法和if -else的差不多,就是在第一个#if要是不满足,那么就看#elif的条件是否满足,要是满足则运行其代码,要是不满足,要是这两个都不满足,那么就会运行#else的内容,然后就结束。

如下:
 

上面的代码其是满足#elif的条件,那么我们看看其是否可以将hehe打印在屏幕上。

运行结果:

 

下面我们试试当前面两个的都不满足,其是否会运行#else的内容:

 

运行结果:

 可以看到确实是如此。

那么细心的同学就会发现了,在我们的多分支条件编译中,会被编译的代码会比不被进行编译的代码颜色更深。

3、判断符号是否被定义

在编译一个程序的时候,如果我们要将一条语句,编译或者放弃编译,那么我们可以使用条件编译,比如调试性的代码,我们在调试完后,将其删去又会很浪费,但是保留又会很难看,影响我们代码的可读性,那么我们就可以使用条件编译,在编译的时候不编译这些调试性代码。

例如我们在开头使用了#define定义一个符号,如果我们没有注释或者删除这个符号,那么我们是可以编译里面的调试性代码的,反之就不可以编译。但是这个是不会影响代码的正常运行的。

我们先学习如何进行判断一个符号是否被定义:

1、使用#if  define进行判断其语法如下:

2、使用#ifdef进行判断:

     

使用#ifdef的话,要判断的符号就不需要使用括号了。

下面我们使用其判读符号是否被定义:

我们首先定义一个GEBUG的符号,然后在main函数中创建一个变量a,然后我们使用#ifdef判断这个GEBUG符号是否被定义,要是被定义了就将这个变量打印出来。

如下:

 

运行结果:

 

我们注释掉它的定义后,那么就不会打印这个变量了:

 

4、判断符号是否没有被定义 

其和上面的判断符号是否被定义差不多:

1、使用#if !defined:这个就是我们上面使用到的#if defined的前面加上一个非符号。

2、使用#ifndef:这个就是在上面的#ifdef加上一个n,表示no实际上就是表示否定。

四、头文件的包含

头文件的包含我们一直都有在使用,其本质上是拷贝,当我们包含一个头文件后,会直接将头文件的内容拷贝过来,下面我们具体学习一下头文件的包含。

1、库头文件的包含

库头文件里面包含了C语言的库函数和一些其他功能,我们只需要包含库的头文件就可以直接使用。

我们包含头文件的语法就是:

#include<头文件>

2、本地头文件的包含

本地头文件就是我们自己写的头文件,这种我们自己实现的头文件的话,我们包含其的语法如下:

#include "头文件"

3、如何避免重复包含头文件

我们在包含头文件中,我们可能会造成嵌套的包含,也就是可能会多次包含同一个头文件,那么这就会造成代码的冗余。

那么我们有没有什么办法解决这个问题呢?

我们可以使用条件编译指令:

就是使用#ifndef或者使用#if  !defined这两个指令。

因为头文件其是就是简单的拷贝,那么我们可以在头文件中的开头写下面的代码:

或者使用预处理指令#pragma

这种方法比上面的还简答,我们可以在当前程序下创建一个头文件,我们可以发现头文件中自动包含了一条语句。

 

这样也可以达到我们想要的效果。

五、C语言完结 

感想各位大佬们的阅读、点赞、收藏和评论,后面我们就会对数据结构的学习。

相关文章:

【C语言】预处理(下)(C语言完结篇)

一、#和## 1、#运算符 这里的#是一个运算符&#xff0c;整个运算符会将宏的参数转换为字符串字面量&#xff0c;它仅可以出现在带参数的宏的替换列表中&#xff0c;我们可以将其理解为字符串化。 我们先看下面的一段代码&#xff1a; 第二个printf中是由两个字符串组成的&am…...

深入理解全排列算法:DFS与回溯的完美结合

全排列问题是算法中的经典问题&#xff0c;其目标是将一组数字的所有可能排列组合列举出来。本文将详细解析如何通过深度优先搜索&#xff08;DFS&#xff09;和回溯法高效生成全排列&#xff0c;并通过模拟递归过程帮助读者彻底掌握其核心思想。 问题描述 给定一个正整数 n&a…...

低频rfid手持机,助力动物耳标智能化管理

低频RFID手持机&#xff0c;助力动物耳标智能化管理&#xff0c;正逐步成为现代畜牧业不可或缺的工具。它不仅能够高效读取动物耳标中的信息&#xff0c;如唯一识别码、疫苗接种记录、健康状态等&#xff0c;还极大地提升了数据录入的准确性和时效性。 1.精准识别与追踪‌ 通过…...

【从零开始学习JVM | 第三篇】虚拟机的垃圾回收学习(一)

堆空间的基本结构 Java 的自动内存管理主要是针对对象内存的回收和对象内存的分配。同时&#xff0c;Java 自动内存管理最核心的功能是 堆 内存中对象的分配与回收。 Java 堆是垃圾收集器管理的主要区域&#xff0c;因此也被称作 GC 堆&#xff08;Garbage Collected Heap&am…...

蓝桥杯之门牌

问题&#xff1a; 这条街一共有 2020 位住户&#xff0c;门牌号从 1 到 2020 编号。 小蓝制作门牌的方法是先制作 0 到9 这几个数字字符&#xff0c;最后根据需要将字符粘贴到门牌上&#xff0c;例如门牌 1017 需要依次粘贴字符 1、0、1、7,即需要 1 个字符 0&#xff0c;2 个…...

Jieba分词的原理及应用(三)

前言 “结巴”中文分词&#xff1a;做最好的 Python 中文分词组件 上一篇文章讲了使用TF-IDF分类器范式进行企业级文本分类的案例。其中提到了中文场景不比英文场景&#xff0c;在喂给模型之前需要进行分词操作。 分词的手段有很多&#xff0c;其中最常用的手段还是Jieba库进行…...

Openlayers:flat样式介绍

在前段时间我在使用WebGL矢量图层时接触到了flat样式&#xff0c;我对其十分的感兴趣&#xff0c;于是我花了几天的时间对其进行了了解&#xff0c;在这篇文章中我将简单的介绍一下flat样式的使用方式以及我对其的一些理解。 一、了解flat样式 1.什么是flat样式&#xff1f; …...

149页研读——华为基于IPD全过程研发质量管理【附全文阅读】

本文介绍了IPD(集成产品开发)的全过程研发质量管理,强调了以客户需求为导向,通过跨部门协同、资源整合、快速响应等方式提高研发效率和成功率。文章详细阐述了IPD研发管理体系的精要,包括其核心思想、优势、框架以及核心理念。 其中,跨领域平台与技术研发、端到端流程与项…...

Linux入门指南:从零开始探索开源世界

引言 欢迎来到Linux的奇妙世界&#xff01;&#x1f30d; 这个诞生于1991年的开源操作系统&#xff0c;如今已悄然成为数字世界的隐形支柱。从智能手机到超级计算机&#xff0c;从智能家电到航天器&#xff0c;Linux的身影无处不在。本文将带你纵览Linux的发展历程、主流发行版…...

Oracle 23ai Vector Search 系列之5 向量索引(Vector Indexes)

文章目录 Oracle 23ai Vector Search 系列之5 向量索引Oracle 23ai支持的向量索引类型内存中的邻居图向量索引 (In-Memory Neighbor Graph Vector Index)磁盘上的邻居分区矢量索引 (Neighbor Partition Vector Index) 创建向量索引HNSW索引IVF索引 向量索引示例参考 Windows 环…...

vue模拟扑克效果

vue模拟扑克效果 效果图&#xff1a; step1:C:\Users\wangrusheng\PycharmProjects\untitled18\src\views\Home.vue <template><div class"poker-container"><!-- 使用复合数据对象实现双行显示 --><divv-for"(card, index) in POKER_…...

Android12源码编译之预置Android Studio项目Android.mk文件编写

1、在AndroidManifest.xml文件中添加package"com.sprd.silentinstalldemo"属性&#xff0c;因为新版本的Android Studio默认生成的AndroidManifest.xml是没有这个属性值的 <?xml version"1.0" encoding"utf-8"?> <manifest xmlns:an…...

高阶函数/柯里化/纯函数

本篇文章主要是介绍一下标题里面的概念&#xff0c;在面试的时候经常文档&#xff0c;结合阅读到的资料&#xff0c;结合本人的个人见解出品了该文章&#xff0c;如有写的不好的地方或理解有误的&#xff0c;还望阁下多多指教。 1、高阶函数 什么是高阶函数&#xff1f; 接受…...

Spring Boot 测试详解,包含maven引入依赖、测试业务层类、REST风格测试和Mock测试

Spring Boot 测试详解 1. 测试依赖引入 Spring Boot 默认通过以下 Maven 依赖引入测试工具&#xff1a; <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</s…...

探索 HTML5 新特性:提升网页开发的现代体验

在 Web 开发的演进历程中&#xff0c;HTML5 无疑是一座重要的里程碑。它不仅为网页带来了更丰富的功能&#xff0c;还提升了开发效率与用户体验。本文将深入探讨 HTML5 那些令人瞩目的新特性&#xff0c;助你紧跟现代 Web 开发潮流。 一、语义化标签&#xff1a;让结构更清晰 …...

Python中如何用正则表达式精准匹配IP地址?

在网络编程和数据处理时&#xff0c;我们经常需要从文本中提取或验证IP地址。Python的正则表达式(re模块)是完成这个任务的利器。但你知道怎么写才能准确匹配各种合法的IP地址吗&#xff1f;今天我们就来详细探讨这个问题。 为什么需要IP正则表达式&#xff1f; 假设你正在分…...

leetcode刷题日记——螺旋矩阵

[ 题目描述 ]&#xff1a; [ 思路 ]&#xff1a; 题目要求按顺时针顺序给出m行n列的矩阵的数组按照题目所给的顺序挨个插入答案数组中运行如下 int* spiralOrder(int** matrix, int matrixSize, int* matrixColSize, int* returnSize) {*returnSize matrixSize * matrixCol…...

金字塔原理学习法

金字塔原理学习法 金字塔原理&#xff08;Pyramid Principle&#xff09; 是由麦肯锡顾问芭芭拉明托提出的结构化思维方法&#xff0c;核心是通过纵向分层、横向归类的逻辑架构组织信息&#xff0c;实现复杂问题的清晰表达与高效学习。在技术学习领域&#xff0c;该原理能有效…...

模板引擎语法-标签

模板引擎语法-标签 文章目录 模板引擎语法-标签[toc]一、用于进行判断的{% if-elif-else-endif %}标签二、关于循环对象的{% for-endfor %}标签三、关于自动转义的{% autoescape-endautoescape %}标签四、关于循环对象的{% cycle %}标签五、关于检查值是否变化的{% ifchange %}…...

深度学习学习笔记

目录 摘要 Abstracts 简介 Hourglass Module&#xff08;Hourglass 模块&#xff09; 网络结构 Intermediate Supervision&#xff08;中间监督&#xff09; 训练过程细节 评测结果 摘要 本周阅读了《Stacked Hourglass Networks for Human Pose Estimation》&#xf…...

当Browser Use遇见A2A:浏览器自动化与智能体协作的“冰与火之歌“

——一场正在改写数字文明的技术奇遇 第一章 浏览器革命&#xff1a;从"手动挡"到"自动驾驶" 1.1 传统自动化工具的"中年危机" 还记得2023年那个抓狂的凌晨吗&#xff1f;你蹲守演唱会门票时&#xff0c;Selenium脚本因为验证码识别失败第108次…...

智能医疗辅助诊断:深度解析与实战教程

引言&#xff1a;医疗领域的新革命 在医疗资源紧张、诊断效率亟待提升的今天&#xff0c;智能医疗辅助诊断技术正以前所未有的速度改变医疗行业的面貌。通过结合人工智能与医学专业知识&#xff0c;智能医疗辅助诊断系统能够为医生提供精准的诊断建议和决策支持&#xff0c;显…...

(已解决)如何安装python离线包及其依赖包 2025最新

字数 305&#xff0c;阅读大约需 2 分钟 没有网络的Linux服务器上&#xff0c;如何安装完整的、离线的python包 1. 写入待安装的包 新建requirement.txt, 写入待安装的包 和 包的版本 如 flwr1.13.0 2.使用命令行直接下载 pip download -d flwr_packages -r requirements.tx…...

Java如何获取文件的编码格式?

Java获取文件的编码格式 在计算机中&#xff0c;文件编码是指将文件内容转换成二进制形式以便存储和传输的过程。常见的文件编码格式包括UTF-8、GBK等。不同的编码使用不同的字符集和字节序列&#xff0c;因此在读取文件时需要正确地确定文件的编码格式 Java提供了多种方式以获…...

豪越赋能消防安全管控,解锁一体化内管“安全密码”

在消防安全保障体系中&#xff0c;内部管理的高效运作是迅速、有效应对火灾及各类灾害事故的重要基础。豪越科技凭借在消防领域的深耕细作与持续创新&#xff0c;深入剖析消防体系内部管理的痛点&#xff0c;以自主研发的消防一体化安全管控平台&#xff0c;为行业发展提供了创…...

Python实现链接KS3,并批量下载KS3文件数据到本地

前言 本文是该专栏的第56篇,后面会持续分享python的各种干货知识,值得关注。 在本专栏的上篇文章《Python实现链接KS3,并将文件数据批量上传到KS3》中,笔者有详细介绍基于Python,实现链接KS3并将文件数据批量上传。而本文,笔者将基于在上一篇文章的基础之上,实现链接KS…...

状态机 XState

以下是关于 状态机(XState) 基本知识的梳理,涵盖核心概念、高级特性、实际应用场景及最佳实践,帮助我们掌握这一强大的状态管理工具: 一、状态机核心概念 1. 有限状态机(Finite State Machine, FSM)基础 定义:系统在有限状态集合中流转,由事件触发状态转换核心要素:…...

Python及C++中的排序

一、Python中的排序 &#xff08;一&#xff09;内置排序函数sorted() 基本用法 sorted()函数可以对所有可迭代对象进行排序操作&#xff0c;返回一个新的列表&#xff0c;原列表不会被修改。例如&#xff0c;对于一个简单的数字列表nums [3, 1, 4, 1, 5, 9, 2, 6]&#xff…...

拓扑排序 —— 2. 力扣刷题207. 课程表

题目链接&#xff1a;https://leetcode.cn/problems/course-schedule/description/ 题目难度&#xff1a;中等 相关标签&#xff1a;拓扑排序 / 广度优先搜搜 BFS / 深度优先搜索 DFS 2.1 问题与分析 2.1.1 原题截图 2.1.2 题目分析 首先&#xff0c;理解题目后必须马上意识到…...

从入门到进阶:React 图片轮播 Carousel 的奇妙世界!

全文目录&#xff1a; 开篇语&#x1f590; 前言✨ 目录&#x1f3af; 什么是图片轮播组件&#xff1f;&#x1f528; 初识 React 中的轮播实现示例代码分析 &#x1f4e6; 基于第三方库快速实现轮播示例&#xff1a;用 react-slick优势局限性 &#x1f6e0;️ 自己动手实现一个…...