【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、#运算符 这里的#是一个运算符,整个运算符会将宏的参数转换为字符串字面量,它仅可以出现在带参数的宏的替换列表中,我们可以将其理解为字符串化。 我们先看下面的一段代码: 第二个printf中是由两个字符串组成的&am…...
IIC通信协议
一、概述 IIC协议:是一种各种电子设备之间进行数据交换和通信的串行,半双工通信协议,主要用于近距离,低速的芯片之间的通信。 I2C协议采用双线结构传输数据,由一个数据线&#…...
SpringBoot原生实现分布式MapReduce计算(无第三方中间件版)
一、架构设计调整 核心组件替换方案: 注册中心 → 数据库注册表任务队列 → 数据库任务表分布式锁 → 数据库行级锁节点通信 → HTTP REST接口 二、数据库表结构设计 -- 节点注册表 CREATE TABLE compute_nodes (node_id VARCHAR(36) PRIMARY KEY,last_heartbea…...
02-libVLC的视频播放器:播放音视频文件以及网络流
libvlc_new(0, nullptr)功能:创建并初始化libVLC的核心实例,是使用所有libVLC功能的前提。 参数:第一个参数:参数数量(通常设为0)第二个参数:参数列表(通常为nullptr,表示使用默认配置)返回值:成功返回libvlc_instance_t*指针,失败返回nullptr。注意事项:可通过参…...
Autoware源码总结
Autoware源码网站 项目简介 教程 Autoware的整体架构如下图,主要包括传感器sensing、高精地图map data、车辆接口vehicle interface、感知perception(动态障碍物检测detection、跟踪tracking、预测prediction;交通信号灯检测detection、分类c…...
PowerBI 条形图显示数值和百分比
数据表: 三个度量值 销售额 SUM(销量表[销售量])//注意, 因为Y轴显示的产品,会被筛选,所以用ALLSELECTED来获取当前筛选条件下,Y轴显示的产品 百分比 FORMAT(DIVIDE([销售额],CALCULATE([销售额],ALLSELECTED(销量表[产品编码]))),"0…...
Sa-Token 自定义插件 —— SPI 机制讲解(一)
前言 博主在使用 Sa-Token 框架的过程中,越用越感叹框架设计的精妙。于是,最近在学习如何给 Sa-Token 贡献自定义框架。为 Sa-Token 的开源尽一份微不足道的力量。我将分三篇文章从 0 到 1 讲解如何为 Sa-Token 自定义一个插件,这一集将是前沿…...
基于 Termux 在移动端配置 Ubuntu 系统并搭建工作环境
本套方案主要参考了以下内容,并根据自身体验进行了修改。 【教程】用Termux搭建桌面级生产力环境Termux安装完整版Linux(Ubuntu)详细步骤 前言 自己的电脑太重,有时候外出不想带,平板生产力有有限。所以一直在折腾用平板替代电脑的事情。之前…...
JAVA SDK通过proxy对接google: GCS/FCM
前言:因为国内调用google相关api需要通过代理访问(不想设置全局代理),所以在代理这里经常遇到问题,先说一下结论 GCS 需要设置全局代理或自定义代理选择器, FCM sdk admin 在初始化firebaseApp时是支持设置的。 GCS: 开始时尝试在…...
JAVA EE_多线程-初阶(三)
我对未来没有底气 我也不知道当下该如何做 那就活着,活着就能把日子过下去 ---------陳長生. 1.多线程案例 1.1.单例模式 单例模式是常见的设计模式之一 设计模式:一些编程大佬制定的一些通用代码,再特定的场景下能套用进去,即…...
@PKU秋招互联网产品经理求职分享
从校园到职场 非常荣幸能够在毕业后两年半再次回到燕园。今天,我主要想和大家分享一下我在互联网行业的求职和工作经验。从最初面对职场的迷茫,到现在能够从容应对职场各种挑战,这一路走来积累了不少心得。互联网行业变化迅速,持续…...
uniapp日常总结--uniapp页面跳转方式
uniapp日常总结--uniapp页面跳转方式_uniapp 跳转-CSDN博客...
【能源节约管理系统行业树组件优化总结】
能源节约管理系统行业树组件优化总结 问题背景 在能源节约管理系统中,我们需要一个行业选择组件,以树形结构展示国民经济行业分类数据。由于行业数据量大且层级多,我们采用了懒加载的方式实现。然而,在编辑和详情模式下…...
青少年编程考试 CCF GESP图形化编程 二级认证真题 2025年3月
图形化编程 二级 2025 年 03 月 一、单选题(共 10 题,每题 3 分,共 30 分) 1、2025 年春节有两件轰动全球的事件,一个是 DeepSeek 横空出世,另一个是贺岁片《哪吒 2》票房惊人,入了全球票房榜…...
【Hadoop入门】Hadoop生态之Flume简介
1 什么是Flume? Flume是Hadoop生态系统中的一个高可靠、高性能的日志收集、聚合和传输系统。它支持在系统中定制各类数据发送方(Source)、接收方(Sink)和数据收集器(Channel),从而能…...
十六、Linus网络编程基础
1、Linux 网络的历史发展 早期阶段(1991–1995) 1991年:Linus Torvalds 发布 Linux 内核的初始版本(0.01),此时内核不支持网络功能,仅是一个单机操作系统。1992年:受 BSD …...
【激活函数:神经网络的“调味料】
1. 激活函数:神经网络的“调味料” 想象你在做菜: 没有激活函数:就像只用水煮食材,味道单调(只能拟合线性关系)。加入激活函数:像加了盐、糖、辣椒,让菜有酸甜苦辣(非线…...
006.Gitlab CICD流水线触发
文章目录 触发方式介绍触发方式类型 触发方式实践分支名触发MR触发tag触发手动人为触发定时任务触发指定文件变更触发结合分支及文件变更触发正则语法触发 触发方式介绍 触发方式类型 Gitlab CICD流水线的触发方式非常灵活,常见的有如下几类触发方式: …...
服务器远程端口详解
服务器远程端口详解 一、服务器远程端口的概念与作用 1. 端口的基本定义 服务器远程端口是计算机网络中用于标识不同应用程序或服务的逻辑接口。通过TCP/IP协议栈的"Socket"机制,计算机可以通过软件方式与其他设备建立通信通道。每个端口对应一个16位无…...
如何在 Vue 3 中实现百度地图位置选择器组件
如何在 Vue 3 中实现百度地图位置选择器组件 前言 在开发前端应用时,地图选择器是一个非常常见的需求。尤其是在一些需要用户选择地址的场景,如电商平台、旅游网站、酒店预定等,百度地图组件能提供准确的地理位置服务。在本文中,…...
es6学习02-let命令和const命令
一、let命令 1.let块级作用域: let关键字 VS var关键字 2.for循环计数器很适合let命令 var:整个for循环中一直都是同一个i在做1,最后输出的就是10; let:每循环一次都是多一个i的赋值,最后输出是可以调出…...
电路方案分析(二十)TPS63xxx系列DC/DC电源EMI PCB设计方案
tips:资料来自网络,仅供学习使用。[TOC](TPS63xxx系列DC/DC电源EMI PCB设计方案) 1.概述 通过TPS63xxx系列DC/DC电源模块来分析降低直流/直流降压/升压转换器辐射 EMI 的来源以及相关PCB设计。 下面都以最常用的TPS63070为例说明: 典型应用…...
DeepSeek大语言模型部署指南:从基础认知到本地实现
目录 一、DeepSeek简介:开源领域的新兴力量 1.1 公司背景与发展历程 1.2 核心产品DeepSeek-R1的技术特点 1.3 行业影响与伦理挑战 二、官方资源获取:全面掌握DeepSeek生态 2.1 官方网站与API服务 2.2 开源代码库资源 2.3 模型部署工具Ollama简介…...
09-设计模式 企业场景 面试题-mk
你之前项目中用过设计模式吗? 需求:设计一个咖啡店点餐系统。 设计一个咖啡类(Coffee),并定义其两个子类(美式咖啡【AmericanCoffee】和拿铁咖啡【LatteCoffee】);再设计一个咖啡店类(CoffeeStore),咖啡店具有点咖啡的功能。具体类图设计如下: 上面的对象都是ne…...
达梦数据库-学习-18-ODBC数据源配置(Linux)
一、环境信息 名称值CPU12th Gen Intel(R) Core(TM) i7-12700H操作系统CentOS Linux release 7.9.2009 (Core)内存4G逻辑核数2DM版本1 DM Database Server 64 V8 2 DB Version: 0x7000c 3 03134284194-20240703-234060-20108 4 Msg Versi…...
解决VS2022中scanf报错C4996
这个的原因是因为新版的VS认为scanf不安全,要去使用scanf_s,但在C语言中就需要scanf,所以我们只要以以下步骤解决就可以了。 只要加入宏定义即可 #define _CRT_SECURE_NO_WARNINGS 因为本人已经很少写小案例了,所以就用这个办法…...
Python(11)Python判断语句全面解析:从基础到高级模式匹配
目录 一、条件逻辑的工程价值1.1 真实项目中的逻辑判断1.2 判断语句类型矩阵 二、基础判断深度解析2.1 多条件联合判断2.2 类型安全判断 三、模式匹配进阶应用3.1 结构化数据匹配3.2 对象模式匹配 四、判断语句优化策略4.1 逻辑表达式优化4.2 性能对比测试 五、典型应用场景实战…...
Quartus II的IP核调用及仿真测试
目录 第一章 什么是IP核?第二章 什么是LPM?第一节 设置LPM_COUNTER模块参数第二节 仿真 第三章 什么是PLL?第一节 设置ALTPLL(嵌入式锁相环)模块参数第二节 仿真 第四章 什么是RAM?第一节 RAM_1PORT的调用第…...
如何修改服务器TTL值
Windows默认返回的TTL值为128,Linux为64,我们怎么修改这个值呢? 目录 一. Windows 二. Linux 临时更改 永久更改 一. Windows WinR输入regedit,打开注册表 路径:计算机\HKEY_LOCAL_MACHINE\SYSTEM\CurrentContro…...
大模型LLM表格报表分析:markitdown文件转markdown,大模型markdown统计分析
整体流程:用markitdown工具文件转markdown,然后大模型markdown统计分析 markitdown https://github.com/microsoft/markitdown 在线体验:https://huggingface.co/spaces/AlirezaF138/Markitdown 安装: pip install markitdown…...
劫持SUID程序提权彻底理解Dirty_Pipe:从源码解析到内核调试
DirtyPipe(CVE-2022-0847)漏洞内核调试全流程指南 本文主要面向对内核漏洞挖掘与调试没有经验的初学者,结合 CVE-2022-0847——著名的 Dirty Pipe 漏洞,带你从零开始学习 Linux 内核调试、漏洞复现、原理分析与漏洞利用。该漏洞危害极大,并且概念简单明了,无需复杂前置知…...
React 组件样式
在这里插入图片描述 分为行内和css文件控制 行内 通过CSS中类名文件控制...
嵌入式人工智能应用-第三章 opencv操作3 图像平滑操作 下
5 高斯噪声(Gaussian Noise) 高斯噪声(Gaussian Noise)是一种符合正态(高斯)分布的随机噪声,广泛存在于传感器采集、信号传输等场景中。以下是关于高斯噪声的详细说明、添加方法及滤波方案。 …...
OSPF的接口网络类型【复习篇】
OSPF在不同网络环境下默认的不同工作方式 [a3]display ospf interface g 0/0/0 # 查看ospf接口的网络类型网络类型OSPF接口的网络类型(工作方式)计时器BMA(以太网)broadcast ,需要DR/BDR的选举hello:10s…...
maven编译jar踩坑[sqlite.db]
背景: 最近在项目中搞多数据源切换的job,在src/resource下有初始化的sqlite默认文件供后续拷贝使用,在测试阶段没有什么问题,但是一部署到服务器上运行就有问题。 报错现象: 找不到这个sqlite.db文件或者文件格式有问题&#x…...
【软考系统架构设计师】软件工程
1、 软件开发生命周期 软件定义时期:包括可行性研究和详细需求分析过程,任务是确定软件开发工程必须完成的总目标,具体分为问题定义、可行性研究、需求分析等 软件开发时期:软件的设计与实现,分为概要设计、详细设计、…...
蓝桥杯单片机刷题——ADC测量电位器的电压
设计要求 通过PCF8591的ADC通道测量电位器RB2的输出电压,并使用套件上提供的USB转串口功能,完成下列程序设计要求。 串口每次接收包含5个字符的字符串, 1)若接收的5个字符中有字符’a’或’A’,则数码管显示一位小数…...
零基础上手Python数据分析 (12):DataFrame 数据清洗与预处理 (下) - 类型转换、格式化、文本与日期处理
写在前面 上一篇博客,我们学习了如何使用 Pandas 处理数据分析中最常见的 “脏数据”:缺失值、重复值和异常值。 这为我们处理数据质量问题打下了坚实的基础。 然而,数据清洗的挑战远不止于此。 在实际数据中,我们还会经常遇到 数据类型不一致、数据格式不规范、文本数据混…...
免费下载 | 2025清华五道口:“十五五”金融规划研究白皮书
《2025清华五道口:“十五五”金融规划研究白皮书》的核心内容主要包括以下几个方面: 一、五年金融规划的重要功能与作用 凝聚共识:五年金融规划是国家金融发展的前瞻性谋划和战略性安排,通过广泛听取社会各界意见,凝…...
制造一只电子喵 (qwen2.5:0.5b 微调 LoRA 使用 llama-factory)
AI (神经网络模型) 可以认为是计算机的一种新的 “编程” 方式. 为了充分利用计算机, 只学习传统的编程 (编程语言/代码) 是不够的, 我们还要掌握 AI. 本文以 qwen2.5 和 llama-factory 举栗, 介绍语言模型 (LLM) 的微调 (LoRA SFT). 为了方便上手, 此处选择使用小模型 (qwen2…...
Java中parallelStream并行流使用指南
Java中parallelStream并行流使用指南 在 Java 中,parallelStream() 是 Java 8 引入的一个用于并行处理集合数据的工具,它基于 Fork/Join框架 实现,能够自动将任务拆分成子任务并利用多核处理器并行执行。以下是对 parallelStream的详细说明和…...
Python及C++中的列表
一、Python中的列表(List) Python的列表是动态数组,内置于语言中,功能强大且易用,非常适合算法竞赛。 1. 基本概念 定义:列表是一个有序、可变的序列,可以存储任意类型的元素(整数…...
mybatis plus 分页查询出来数据后对他二次 修改数据 封装返回
mybatis plus 分页查询出来数据后对他二次 修改数据 封装返回 /*** 搜索问卷** param keyword* param pageNo* param pageSize* return*/AutoLog(value "v_survey-搜索")ApiOperation(value"v_survey-搜索", notes"v_survey-搜索")GetMapping(v…...
海洋大地测量基准与水下导航系列之八我国海洋水下定位装备发展现状
中国国家综合PNT体系建设重点可概括为“51N”,“5”指5大基础设施,包括重点推进下一代北斗卫星导航系统、积极发展低轨导航增强系统、按需发展水下导航系统、大力发展惯性导航系统、积极探索脉冲星导航系统;“1”是实现1个融合发展࿰…...
基于单片机的电梯智能识别电动车阻车系统设计与实现
标题:基于单片机的电梯智能识别电动车阻车系统设计与实现 内容:1.摘要 随着电动车在日常生活中的普及,将电动车带入电梯带来的安全隐患日益凸显,如引发火灾等。本研究的目的是设计并实现一种基于单片机的电梯智能识别电动车阻车系统。方法上,…...
什么是柜台债
柜台债(柜台债券业务)是指通过银行等金融机构的营业网点或电子渠道,为投资者提供债券买卖、托管、结算等服务的业务模式。它允许个人、企业及机构投资者直接参与银行间债券市场的交易,打破了以往仅限机构参与的壁垒。以下是综合多…...
.py文件和.ipynb文件的区别:完整教程
一、概述 Python开发者常用的两种文件格式.py和.ipynb各有特点,本教程将通过对比分析、代码示例和场景说明,帮助开发者全面理解二者的区别与联系。 二、核心区别对比 1. 文件格式本质 特性.ipynb文件.py文件文件类型JSON结构化文档纯文本文件存储内容…...
Python中NumPy的逻辑和比较
在数据科学和科学计算领域,NumPy是一个不可或缺的Python库。它提供了高效的多维数组对象以及丰富的数组操作函数,其中逻辑和比较操作是NumPy的核心功能之一。通过灵活运用这些操作,我们可以轻松实现数据筛选、条件判断和复杂的数据处理任务。…...
tt_Docker
快速上手 查看 Docker 服务运行状态;查看本地镜像;从 Docker Hub 拉取基础镜像, 我们此处选择 ubuntu:18.04 镜像;再次查看本地镜像;使用 ubuntu:18.04 镜像构建容器,并交互式运行容器;在容器内部执行 LS 命令;退出容器;查看本地容器实例;再次启动停止的…...
虚幻引擎5-Unreal Engine笔记之“将MyStudent变量设置为一个BP_Student的实例”这句话如何理解?
虚幻引擎5-Unreal Engine笔记之“将MyStudent变量设置为一个BP_Student的实例”这句话如何理解? code review! 文章目录 虚幻引擎5-Unreal Engine笔记之“将MyStudent变量设置为一个BP_Student的实例”这句话如何理解?理解这句话的关键点1.类(…...