预处理详解1❤

 一:预定义符号

C语言中设置了一些预定义符号,它们可以直接使用,同时预定义符号是在预处理期间处理的。

以下就是相关的预处理符号的作用。

 二:#define定义常量

首先基本的语法是  #define name stuff    相对比较简单,就不多赘述了。

但是有些朋友就有所困惑了,这个最后是否要加";",这里声明一下是不用加的。

三:#define定义宏

#define 机制包括了⼀个规定,允许把参数替换到⽂本中,这种实现通常称为宏(macro)或定义宏 (define macro)。

申请宏的基本形式是

#define name(paramentf-list) stuff
这里需要注意一下,name的后面是不能空格的,括号应该与name紧密相连。如果有空隙的话就会被解释成stuff的一部分。

这样看着并不是很好懂,我们接下来就举一个例子来理解其中的意思。

#define SQUARE(x) x*x
int a=3;
printf("%d/n",AQUARE(a));
这个宏接收⼀个参数 x .如果在上述声明之后,你把 SQUARE( 3 ); 置于程序中,预处理器就会⽤
下⾯这个表达式替换上⾯的表达式: 3 * 3

注意: 

宏使用不当也存在一定的问题。我们可以观察下面的代码段。

#define SQUARE(x) x*x
int a=3;
printf("%d/n",AQUARE(a+1));
这个乍一看是两个4相乘为16,但是恰恰不同,这个结果是7,
因为在替换文本的时候,参数x被换成a+1,那么就是a+1*a+1,这个时候就要遵循运算法则,计算的结果是2a+1.
所以我们可以加两个括号,来避免这种错误。
#define SQUARE(x) (x)*(x);这样就是(a+1)*(a+1),避免了那种错误。
但是这种也并非十分的完美。我们可以继续看下面的例子。#define SQUARE(x) (x)+(x)
int a=3;
printf("%d/n",10*AQUARE(a+1));
有同学就会大意的认为这个是90,这个结果是不对的。打印出来的结果是33,错误与上面的差不多,带入进去就是
10*(3)+3;
对于这种情况我们的解决办法是在宏定义表达式两边加上⼀对括号就可以了。
#define SQUARE(x) ((x)+(x))。这个就比较完美了。

注意:

所以用于对数值表达式进行求值的宏定义都应该用这种方式加上括号,避免在使用宏时由于参数中的操作符或邻近操作符之间不可预料的相互作用。 

四:带有副作用的宏函数

当宏参数在宏的定义中出现超过⼀次的时候,如果参数带有副作用,那么你在使用这个宏的时候就可能出现危险,导致不可预测的后果。副作用就是表达式求值的时候出现的永久性效果。

这句话并不好理解。我们可以举举几个例子来了解其中的意思。

写一个宏,求2个整数的较大值
#define MAX(x,y) ((x)>(y)?(x):(y))int main()
{int a = 3;int b = 5;scanf("%d %d", &a, &b);int m = MAX(a++, b++);int m = ((a++)>(b++)?(a++):(b++));printf("m = %d\n", m);printf("a = %d\n", a);printf("b = %d\n", b);return 0;}

我们可以一步步分析,来解除相应的答案。

首先我们需要将参数带入到宏中,((a++)>(b++)?(a++):(b++));

此时++在后面,那么就是先比较大小然后再加。比较之后b大,然后再加1,此时a为4,b为6.在接下来,到(a++):(b++)这一步因为先使用后加所以m就赋值为6,b再加1.b就为7.

那么答案就是

m=6 a=4 b=7.

如果不是很清晰的话可以参考下面的图片。

五:宏替换的规则

在程序中扩展#define定义符号和宏时,需要涉及几个步骤。

1. 在调用宏时,首先对参数进行检查,看看是否包含任何由#define定义的符号。如果是,它们首先被替换。

2. 替换文本随后被插入到程序中原来文本的位置。对于宏,参数名被他们的值所替换

3. 最后,再次对结果文件进行扫描,看看它是否包含任何由#define定义的符号。如果是,就重复上述处理过程。

注意:

1.宏参数和#define 定义中可以出现其他#define定义的符号。但是对于宏,不能出现递归。

2. 当预处理器搜索#define定义的符号的时候,字符串常量的内容并不被搜索。

这里的字符串常量并不被搜索的意思是


     printf("m = %d\n", m);这里面双引号的m并不被替换。

六:宏函数的对比

我们可以总结成下面的表格 

希望各位看官有所收获,也麻烦公主少爷们三连,谢谢!!!!! 

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CSDN年度报告图片卡通小人收集

摘要:CSDN推出的年度报告真的太赞了,还定制了诸如“情感的编织者”“敏锐的激励者”“灵感的捕捉者”“组织的表达者”“洞悉的指挥家”“心灵的领航员”“生动的记录者”“温暖的叙述者”“理性的探索者”等等精准且浪漫的标签,加上非常有灵…

【Web】CTFSHOW SQL注入刷题记录(上)

目录 无过滤注入 web171 web172 web173 web174 web175 时间盲注 写马 过滤注入 web176 web177 web178 web179 web180 web181-182 web183 web184 web185-186 web187 web188 web189 web190 布尔盲注 web191 web192 web193 web194 堆叠注入 web195 …

Stable Diffusion插件Recolor实现黑白照片上色

今天跟大家分享一个使用Recolor插件通过SD实现老旧照片轻松变彩色,Recolor翻译过来的含义就是重上色,该模型可以保持图片的构图,它只会负责上色,图片不会发生任何变化。 一:插件下载地址 https://github.com/pkuliyi…

OSPF协议解析及相关技术探索(C/C++代码实现)

OSPF(开放最短路径优先)是一种用于自治系统(AS)内部的路由协议,它是基于链路状态算法的。OSPF的设计目的是为了提供一种可扩展、快速收敛和高效的路由解决方案。 OSPF概念和特点 概念 自治系统(AS&#…

战略合作 | IAR全面支持云途车规级MCU

IAR嵌入式开发解决方案现已全面支持云途半导体YTM32系列MCU,携手合作伙伴共同助力高端创新应用的开发 中国,上海 – 2024年1月26日 – 嵌入式开发软件和服务的全球领导者IAR与知名国产汽车芯片公司江苏云途半导体有限公司(以下简称“云途半导…

JavaScript学习-原型和原型链

原型和原型链 示例代码 //创建一个Person类 class Person {constructor(name) {this.name name;}drink() {console.log(喝水);} } //创建一个Teacher类,继承Person class Teacher extends Person {constructor(name, subject) {super(name);this.subject subjec…

react 实现页面状态缓存(keep-alive)

前言: 因为 react、vue都是单页面应用,路由跳转时,就会销毁上一个页面的组件。但是有些项目不想被销毁,想保存状态。 比如:h5项目跳转其他页面返回时,页面状态不丢失。设想一个 页面我滑倒了中间&#xf…

Linux(2)——Linux中的Vim编辑器:从入门到精通

Linux中的Vim编辑器:从入门到精通 插播!插播!插播!亲爱的朋友们,我们的Cmake/Makefile/Shell这三个课程上线啦!感兴趣的小伙伴可以去下面的链接学习哦~ 构建工具大师-CSDN程序员研修院 一、Vim的基本概念…

量子网络是什么

量子网络是基于量子力学规律对量子信息进行存储、处理和传输的物理装置,是实现量子通讯和大规模量子计算的基础。清华大学研究团队利用同种离子的双类型量子比特编码,在国际上首次实现无串扰的量子网络节点,对未来实现量子通讯和大规模量子计…

蓝桥杯备战——3.定时器前后台

1.STC15F2k61S2的定时器 阅读STC15系列的手册,我们可以看到跟STC89C52RC的定时器还是有不同之处的: 由上图可以看到我们可以通过AUXR寄存器直接设置定时器的1T/12T模式了 在定时器0/1模式上也可以设置为16位自动重装载。 另外需要注意IAP15F2K61S2只有…

Unity中实现合理塔防寻路机制

前言 在一款TD游戏中,最重要的单位就两大类:防御塔(Tower)和敌人单位(Enemy)。在处理敌人单位的AI行为时,最基本也是最重要的就是自动寻路。在各式TD游戏中,防御塔的攻击方式以及敌人单位的Buff机制往往是能做出差异化的地方;而在寻路问题上,几乎是没有差异的,面对…

Kettle-Docker部署+Sqlserver数据同步Mysql+Start定时任务

一. 背景介绍 1. ETL是什么 ETL(Extract-Transform-Load),即数据抽取、转换、装载的过程。它是一种思想,主要是说,从不同的数据源获取数据,并通过对数据进行处理(格式,协议等转换&a…

unity学习笔记----游戏练习07

一、僵尸攻击和植物的掉血和销毁 当僵尸接触到植物开始攻击时会持续削减植物的血量,当植物血量为零时就销毁当前植物。 在plantManager中, 为植物添加一个血量HP 100, public int HP 100; 在写一个减少血量的方法,来减少血…

NC65中间件能启动,前端客户端启动失败,加载异常,卡住(org.owasp.esapi)

控制台输出错误 ESAPI.properties could not be loaded by any means. Fail.SecurityConfiguration class(org.owasp.esapi.reference.DefaultSecurityConfiguration) CTOR threw exception.效果图: 解决方案 添加如下参数: -Dorg.owasp.esapi.resou…

cocos creator 碰撞系统

设置碰撞组件 3种组件类型,矩形碰撞,圆形碰撞, 多边形碰撞 开启碰撞检测 start() {//开启碰撞管理器let cm cc.director.getCollisionManager()cm.enabled true//绘制碰撞检测边界线。用于调试cm.enabledDebugDraw true//绘制精灵的边界c…

docker 修改默认存储位置

✨✨✨✨✨✨✨ 🎀前言🎁查看前面docker储存位置🎁移动文件位置🎁修改配置文件docker.service🎁修改daemon.json🎁加载配置并重启 🎀前言 最近服务出现系统盘满了,发现其中docker存储占用很大一…

nginx使用stream模块代理端口

今天原本准备将本地金仓的54321端口进行代理的,但是发现代理后总是无法访问。后来突然发现之前使用nginx代理的是一个地址而不是端口。因此做以下笔记用来做记录。 一、stream安装与配置 假设nginx在usr/local/nginx中 1. 测试当前nginx是否有stream模块 ./usr/…

实用工具合集(持续更新...)

一、搜索引擎 1.1、小白盘 网站:https://www.xiaobaipan.com 度盘资源搜索的网站,能够搜索电影、电视剧、小说、音乐等资源(注意:评论区很多小伙伴说小白盘有毒,我用谷歌浏览器搜索过几次并无大碍,请慎用…

wpf控件Expander集合下的像素滚动

项目场景:Expander集合滚动 如下图,有一个Expander集合,且设置 ScrollViewer.VerticalScrollBarVisibility "Auto" 每个Expaner下包含有若干元素,当打开Expader(即IsExpanded "true")时&#…

五分钟教会你如何制作宠物服务小程序

随着宠物市场的不断扩大和人们对宠物健康和幸福的关注度越来越高,宠物服务行业也迅速崛起。作为一名有志于创业的宠物爱好者,搭建一款宠物小程序是一个很好的切入点。本文将为大家介绍使用第三方制作平台乔拓云网搭建宠物小程序的全攻略。 第一步&#x…