#define定义宏

#define的定义范围

 

#define不光可以定义变量,常量,还可以定义几乎所有的东西,因为#define可以定义一串代码(即宏),所以包含在代码中的东西都能被定义。

 


#define定义宏



定义是宏名必须于它的参数括号紧挨,中间不能有任何符号,空格都不行。

宏中传参的时候是直接把传进去的参数直接替换,而不是先计算表达式再传参。

所以如果你的参数只有一个,但你却传了一个表达式,他会把这个表达式直接替换进去,这个时候如果不加括号,肯定就会出现错误。

ee5d1d0bb9424b339a195a9a7a5472a9.png 

 因为*的优先级大于+,所以他得到的结果不是36,而是11。

 

此时加上括号就可以解决

即   square(x) (X)*(X)

 

其实光给X打括号还不够安全

4c4302319efa4fc2953ad8a4e175270d.png

我们想要的来是,3传进去得到6,6在与10相乘得到60

 

但其实实际得到的结果是33。

 

此时如果在在两个x的后打一个包括两个X的括号,就可以解决。

即   square(x)((X)*(X))

 

所以为了安全,尽量给宏的参数和整个宏的内容都打上括号。

 


#define替换规则



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

 

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

 

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

 

宏参数和#define定义中可以出现其他#define定义的符号。

但是对于宏,不能递归。

当预处理器搜索#define定义的符号的时候,字符串中的内容并不被搜索和改变

 


宏的内容中的#的作用



的作用是,放在参数的前面

可以将传进来的参数变成对应的字符串。

 

例   假设传进去的参数是abcd,如果你在宏的内容中的参数前加了#,他就会被修改为"abcd"


宏中的##的作用



将##两边的符号合成一个符号,但是合成之后的符号必须是定义过的

例:如果宏中有sum##a,在执行程序的时候,sum##就相当于suma被使用

 

##也可以放在宏参数和宏参数之间或者宏参数和符号之间

4554b832d54e430e9c093d13b3601ab1.png

 


带副作用的宏参数



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

 

e9ce7892d5e14a64ab0d04c61f1c8cdb.png

 上图的宏参数传了a++和b++,传入了MAX后的代码相当于106行写的代码。

 

可以看到a和b都在宏中被多次赋值,得到的结果,可能不是我们想要的结果。

 

而且宏不像函数传值调用时函数调用结束后不改变实参,


宏调用之后不管你是传值还是传地址,传入的参数只要在宏中改变了,宏调用结束后,实参也会被改变。


所以MAX调用结束后m的值为6,a的值为7,b的值为5

所以使用宏时参数尽量不要使用有副作用的参数。

 


宏对于函数的优缺点


优点:

1.因为宏是在预处理的时候就编译了,运行的时候不用再编译,只需要执行计算就可以,所以用于调用函数和从函数返回的代码可能比实际执行这个小型计算工作所需要的时间更多。所以宏比函数在程序的规模和速度方面更胜一筹。

 

2.更为重要的是函数的参数必须声明为特定的类型,而宏不用

所以函数只能在类型合适的表达式上使用。反之这个宏怎可以适用于整形、长整型、浮点型等可以用于>来比较的类型。

 

缺点:

1.每次使用宏的时候,一份宏定义的代码将插入到程序中。除非宏比较短,否则可能大幅度增加程序的长度。

2.宏是没法调试的。

3.宏由于类型无关,也就不够严谨。

4.宏可能会带来运算符优先级的问题,导致程容易出现错。

5、宏不能递归。

 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

web自动化上传文件

1,web 自动化文件上传不要太简单 熟悉 web 自动化测试的大佬应该都懂,当采用 js 调用原生控件进行文件上传的时候,最常用的是使用 pywin32 等系统交互库。 当看到 pywin32 那丑陋的 api 封装只能爆粗口。就为了输入一个文件地址,…

再获认可,YashanDB入选工信部电子一所“2023年数字化转型自主创新解决方案优选案例”

近日,由国家工业信息安全发展研究中心(工业和信息化部电子第一研究所)主办的“数智赋能 创新领航”2023年数字化转型自主创新解决方案优选案例正式公布。深圳计算科学研究院(简称:深算院)自主研发的崖山数据…

校园安全风险管理系统

随着社会的不断发展和进步,教育行业也逐渐走向了信息化、智能化管理。校园作为教育事业的重要场所,其安全和管理问题一直备受关注。为了确保校园的安全和管理,各种校园管理平台应运而生。 其中,凡尔码搭建的校园安全管理系统为校园…

AVL树(超详解)

文章目录 前言AVL树的概念AVL树的实现定义AVL树insert 单旋左单旋右单旋左单旋代码右单旋代码 双旋左右双旋右左双旋 测试AVL树的性能 前言 AVL树是怎么来的呢? 我们知道搜索二叉树会存在退化问题,退化以后就变成单支或者接近单支。 它的效率就变成O(N)…

react 之 美团案例

1.案例展示 2.环境搭建 克隆项目到本地(内置了基础静态组件和模版) git clone http://git.itcast.cn/heimaqianduan/redux-meituan.git 安装所有依赖 npm i 启动mock服务(内置了json-server) npm run serve 启动前端服务 npm…

【React源码 - ReactDom.render发生了什么】

在React开发中,在入口文件我们都会执行ReactDom.render来讲整个应用挂载在主document中,那其中发生了什么,React是如何讲我们写的JSX代码,一步一步更新Fiber进而挂载渲染的呢。本文主要是基于react17.0.2的源码以及自己的理解来简…

linux 内核模块

linux 内核模块 1. 内核相关命令与文件内核模块存放位置查看已加载内核模块加载与卸载内核模块修改内核参数永久调整内核参数 2. 常用模块进程调度模块进程间通信模块内存管理模块文件系统模块网络接口模块 Linux 内核采用的是模块化技术,这样的设计使得系统内核可以…

Jmeter吞吐量控制器总结

吞吐量控制器(Throughput Controller) 场景: 在同一个线程组里, 有10个并发, 7个做A业务, 3个做B业务,要模拟这种场景,可以通过吞吐量模拟器来实现。 添加吞吐量控制器 用法1: Percent Executions 在一个线程组内分别建立两个吞吐量控制器, 分别放业务A和业务B …

Docker本地部署开源浏览器Firefox并远程访问进行测试

文章目录 1. 部署Firefox2. 本地访问Firefox3. Linux安装Cpolar4. 配置Firefox公网地址5. 远程访问Firefox6. 固定Firefox公网地址7. 固定地址访问Firefox Firefox是一款免费开源的网页浏览器,由Mozilla基金会开发和维护。它是第一个成功挑战微软Internet Explorer浏…

KaiwuDB 受邀亮相“ACDU 中国行”数据库技术沙龙(西安站)

12月23日,由中国计算机学会(CCF)指导,浪潮数据库、中国数据库联盟、墨天轮数据库社区等联合主办的“ACDU 中国行”数据库技术发展与实践沙龙(西安站)成功举办。KaiwuDB 高级架构师赵衎衎受邀出席沙龙并做主…

C++ Qt开发:SqlRelationalTable关联表组件

Qt 是一个跨平台C图形界面开发库,利用Qt可以快速开发跨平台窗体应用程序,在Qt中我们可以通过拖拽的方式将不同组件放到指定的位置,实现图形化开发极大的方便了开发效率,本章将重点介绍SqlRelationalTable关联表组件的常用方法及灵…

【C语言】程序练习(三)

大家好,这里是争做图书馆扫地僧的小白。非常感谢各位的支持,也期待着您的关注。 目前博主有着C语言、C、linux以及数据结构的专栏,内容正在逐步的更新。 希望对各位朋友有所帮助同时也期望可以得到各位的支持,有任何问题欢迎私信与…

【华为数据之道学习笔记】7-3基于物理世界的“硬感知”能力

“硬感知”能力的分类 数据采集方式主要经历了人工采集和自动采集两个阶段。自动采集技术仍在发展中,不同的应用领域所使用的具体技术手段也不同。基于物理世界的“硬感知”依靠的就是数据采集,是将物理对象镜像到数字世界中的主要通道,是构建…

进阶版求字符串长度

大家好呀!!!我是Beilef,一个努力的跨界者,今天带来的每日一题是用简单的函数还有递归求字符串长度。下面开始啦,不对的地方请留言。感谢您的斧正。 文章目录 目录 文章目录 前言 一、题目展示 解题思路&am…

Mybatis行为配置之Ⅳ—日志

专栏精选 引入Mybatis Mybatis的快速入门 Mybatis的增删改查扩展功能说明 mapper映射的参数和结果 Mybatis复杂类型的结果映射 Mybatis基于注解的结果映射 Mybatis枚举类型处理和类型处理器 再谈动态SQL Mybatis配置入门 Mybatis行为配置之Ⅰ—缓存 Mybatis行为配置…

HCIA-Datacom题库(自己整理分类的)——ARP协议【完】

一、单选 1.ARP 属于哪一层协议? 数据链路层 网络层 物理层 传输层 2.ARP请求是____发送的 点播 广播 组播 单播 关于ARP报文的说法错误的是? ARP请求报文是广播发送的 ARP报文不能被转发到其他广播域 ARP应答报文是单播方发送的 任何链路层协议都需…

java spring boot 自定义 aop

以一个锁的加锁和释放为例 1、先定义注解 /*** 锁切面* author fmj*/ Retention(RetentionPolicy.RUNTIME) Target(ElementType.METHOD) public interface VersionLockAOP { }2、然后定义切面类以及切点 /*** 切面*/ Component Aspect Slf4j public class VersionLockAOPAspe…

Jackson—Anti-Human IgE Antibodies

Jackson lmmunoResearch推出一系列适用于诊断试剂研发的Mouse Monoclonal Anti-Human IgE antibodies(小鼠抗人IgE单克隆抗体),补充了Jackson现有的抗人lgG、IgM和lgA抗体产品,抗人IgE可与一系列特定的报告分子偶联(如…

融汇贯通 —— 2023年技术与心灵的双重成长旅程

当我们站在2023年的岁末,回望这一年赋予我们的经历和挑战,心中涌动的感慨与启示像朝日初升的光芒,照亮脚下的路,亦照见心中的路。在此,我想分享几个方面的感悟和成长,愿它们能有所触动,成为您前…

上升到人生法则的贝叶斯理论

贝叶斯定理在数据分析、机器学习和人工智能等领域有广泛的应用。贝叶斯定理(Bayes’ theorem)是一种用于计算条件概率的重要定理,它基于条件概率的定义,描述了在已知某一条件下,另一个条件发生的概率。 需要注意的是&a…