预处理详解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.mfbz.cn/a/350708.html

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

相关文章

Dijkstra求最短路 I——朴素版Dijkstra算法

问题描述 稠密图使用朴素版Dijkstra算法 使用邻接矩阵存储图定义dist[]数组用来表示图中所有点到1号点的距离,初始化所有点到1号点的距离为0x3f3f3f3f,dist[1] 0循环n次 在图中找出距离1号点最小的点,并且当前点没有被确定过,另…

服务器无法访问外网怎么办

目前是互联网时代,网络已经成为人们日常生活中不可或缺的一部分。我们通过网络获取信息、进行沟通、甚至进行工作,因此,保持网络的稳定和通畅是非常重要的。然而,有时候我们可能会遇到一些网络无法访问外网的问题,这给…

Odoo14 中的小部件列表

们有不同类型的小部件用于不同的目的,帮助我们简化操作。小部件用于使代码变得简单且用户友好,这将有助于软件的编码和编程方面。在 Odoo 14 开发中,我们可以利用不同的小部件,这些小部件可用于编程操作的某些特定方面。这些简化工…

黑豹程序员-vue实现两级联动下拉列表

需求 在开发中这类需求很多,前后两个下拉框有紧密关系,第一个下拉框相当于一个分类,选中第一个下拉框中的某个分类后,第二个下拉框的内容随之改变,列出其分类下的选项。 图例 选中某个一级风险领域后,二级…

38、Flink 的CDC 格式:canal部署以及示例

Flink 系列文章 一、Flink 专栏 Flink 专栏系统介绍某一知识点,并辅以具体的示例进行说明。 1、Flink 部署系列 本部分介绍Flink的部署、配置相关基础内容。 2、Flink基础系列 本部分介绍Flink 的基础部分,比如术语、架构、编程模型、编程指南、基本的…

蓝牙----蓝牙协议栈Host层

蓝牙协议栈----Host层 蓝牙物理层基本信息链路层的状态机进入连接态的步骤主动扫描与被动扫描链路层通信模式 蓝牙地址蓝牙设备地址蓝牙标识地址蓝牙接入地址 蓝牙广播信道管理蓝牙数据信道跳频 蓝牙协议栈Host层包括PHY、LL、HCL层,注重关注PHY物理层和LL链路层。 …

【RT-DETR有效改进】轻量化ConvNeXtV2全卷积掩码自编码器网络

前言 大家好,我是Snu77,这里是RT-DETR有效涨点专栏。 本专栏的内容为根据ultralytics版本的RT-DETR进行改进,内容持续更新,每周更新文章数量3-10篇。 专栏以ResNet18、ResNet50为基础修改版本,同时修改内容也支持Re…

Leetcode:二分搜索树层次遍历

题目: 给你二叉树的根节点 root ,返回其节点值的 层序遍历 。 (即逐层地,从左到右访问所有节点)。 示例: 示例 1: 输入:root [3,9,20,null,null,15,7] 输出:[[3],[9,…

研发日记,Matlab/Simulink避坑指南(五)——CAN解包 DLC Bug

文章目录 前言 背景介绍 问题描述 分析排查 解决方案 总结 前言 见《研发日记,Matlab/Simulink避坑指南(一)——Data Store Memory模块执行时序Bug》 见《研发日记,Matlab/Simulink避坑指南(二)——非对称数据溢出Bug》 见《…

springboot 项目,返回的实体类里面字段是null ,现在想要为空应该是““,空字符串,而不是null

目录 1 问题2 实现 1 问题 返回给前端的数据,如果数据库的字段没有数据,给返回的是null 要变成这个,全局都变成这样 2 实现 springboot返回给页面的json数据中,如果有数据为null,则返回空字符串。 springboot默认使…

同为科技(TOWE)自动控制循环定时插座

随着科技的发展,智能化家居已成为我们生活的重要组成部分。作为国内领先的智能家居品牌,同为科技(TOWE)推出的自动控制循环定时插座,无疑将科技与生活完美地结合在一起。 1.外观设计 同为科技(TOWE&#x…

Spring第二天

今日目标 能够掌握注解开发定义Bean对象 能够掌握纯注解开发模式 能够配置注解开发依赖注入 能够配置注解开发管理第三方Bean 能够配置注解开发为第三方Bean注入资源 能够使用Spring整合Mybatis 能够使用Spring整合Junit 一、第三方资源配置管理 说明:以管理DataSo…

保险箱(第十四届蓝桥杯省赛PythonB组)

小蓝有一个保险箱,保险箱上共有 n 位数字。 小蓝可以任意调整保险箱上的每个数字,每一次操作可以将其中一位增加 1 或减少 1。 当某位原本为 9 或 0 时可能会向前(左边)进位/退位,当最高位(左边第一位&am…

AM5-DB低压备自投装置在河北冠益荣信科技公司洞庭变电站工程中的应用——安科瑞赵嘉敏

摘 要:随着电力需求的不断增加,电力系统供电可靠性要求越来越高,许多供电系统已具备两回或多回供电线路。备用电源自动投入装置可以有效提高供电的可靠性,该类装置能够在工作电源因故障断开后,自动且迅速地将备用电源投…

Lisflood

3.耦合LisFlood模型 C解决方案在\LisFlood\LISFLOOD-FP-trunk 执行在LisFlood\LISFLOOD-FP-trunk\out\build\msvc-x64-Debug 3.1输入文件 文献:基于SWMM和LISF&#…

vue day06

1、路由模块封装 2、声明式导航 实现导航高亮效果 直接通过这两个类名对相应标签设置样式 点击a链接进入my页面时,a链接 我的音乐高亮,同时my下的a、b页面中的 我的音乐也有router-link-active类,但没有精确匹配的类(只有my页…

HTTP连接池在Java中的应用:轻松应对网络拥堵

网络拥堵是现代生活中无法避免的问题,尤其是在我们这个“点点点”时代,网页加载速度直接影响到我们的心情。此时,我们需要一位“救世主”——HTTP连接池。今天,就让我们一起探讨一下,这位“救世主”如何在Java中大显神…

12个强大的 JavaScript 动画库,可帮助你提升用户体验

文章目录 12个强大的 JavaScript 动画库,可帮助你提升用户体验1.Anime.js2.Lottie3. Velocity4.Rough Notation5.Popmotion6. Vivus7.GSAP:Green Stocking Animation Platform8. Three.js9.ScrollReveal10.Barba.js11.Mo.js12.Typed.js总结 12个强大的 J…

【Python】01快速上手爬虫案例一:搞定豆瓣读书

文章目录 前言一、VSCodePython环境搭建二、爬虫案例一1、爬取第一页数据2、爬取所有页数据3、格式化html数据4、导出excel文件 前言 实战是最好的老师,直接案例操作,快速上手。 案例一,爬取数据,最终效果图: 一、VS…

降维(Dimensionality Reduction)

1.动机一:数据可视化 将数据可视化,我们便能寻找到一个更好的解决方案,降维可以帮助我们。 假使我们有有关于许多不同国家的数据,每一个特征向量都有 50 个特征(如 GDP,人均 GDP,平均寿命等&a…
最新文章