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

news2025/4/18 20:29:39

一、预定义符号

前面我们学习了C语言的编译和链接。

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

如下:

可以看到上面的预定义符号,其都有两个短下划线,要注意的是,这两个短下滑一定不能少,而且这两个下划线之间是没有空的,其是挨在一起的。

下面我们来详细了解这几个预定义符号,

1、_ _FILE_ _代表当前进行边编译的源文件,在打印时,要使用占位符%s,其不单单会打印文件名,还会将文件的完整路径打印出来。

2、_ _LINE_ _代表出现这个预定义符号的行号,例如这个预定义的符号出现在第6行,那么其就为6,那么其打印就使用%d占位符。

3、_ _DATE_ _代表文件被编译的日期,打印的时候使用%s占位符。

4、_ _TLME_ _代表文件被编译的具体时间,具体到时分秒,打印的时候也是使用占位符%s。

5、_ _STDC_ _就和编译文件的编译器有联系了,当前我们的编译器要是支持ANSI  C的标准,那么其就会被定义,其值为1,反之则报错。

下面我们使用这几个预定义符号:

  

下面我们运行看看:

 我们可以看到上面的运行结果,首先_ _FILE_ _其将我们这个文件的完整路径打印出来了。

然后_ _LINE_ _其就会标识当前所在的行数,然后我们打印出来的就是8。

_ _DATE_ _代表是文件编译的时间。

_ _TLME_ _其表示具体的时间,精确到时分秒。

那么为啥我们上面不使用第五个预定义符号呢?

这是因为我们不知道当前的编译器是否支持ANSI  C,要是不支持那么程序就会报错了,所以我们下面单独使用其看看我们当前的环境是否支持:

可以看到我们写代码的时候编译器就已经报错了,下面我们运行看看其错误:

二、#define定义常量

这个关键字我们在前面的学习也已经遇到过了,下面我们来详细学习。

其定义常量的语法如下:

 那么M就是我们定义的常量的名字,100是我们定义的常量的值。

我们可以使用#define来定义各种类型的常量,我们使用其定义常量,对于常量的名字有个约定,就是对名字最好使用全部大写。

这个定义常量,其本质上是替换,其在预处理后,会将程序中的M替换成100。

所以我们使用#define定义常量的时候,末尾不要加分号,因为其会将这个分号也当成常量替换进我们的程序。

如下:

可以看到此时的编译器已经报错了。

所以为了避免一些错误,我们使用#define来定义一个常量的时候,末尾不要加分号;

三、#define定义宏 

#define机制中有个规定,允许将参数替换到文本中去,这种实现通常称为宏或定义宏。

如下:

 其中parament-list是由一个逗号隔开的符号表,它们可能出现在stuf中。

要注意的是:参数列表的左边括号一定要和名字紧紧相邻,不要空格,不然参数就会被解释成stuf的部分了。

下面我们通过一个例子来理解:

我们发现上面宏的形式和我们的函数有点像,前面部分就相当于我们的函数名,括号里面的就相当于函数参数,不过其没有限制数据的类型,最后面的部分就相当于我们的函数体。

 其实际上是替换的规则,比如SQUARE(5),那么预处理后就会将这个语句转化为5*5。

注意:

那个括号要个宏的名字紧紧挨在一起,不然可能会导致这部分被认为是后面的部分。

还有就是宏是将括号里面的x直接替换到后面的x,那么我们看看下面的写法:

我们首先是想求a+1的平方的,然后我们就传了个a+1进去替换,那么在这个语句中实际上是这样的:

a+1*a+1;

那么我们将a=5代入求得结果应该为11;那么就不是我们想要得到的结果了。

我们可以看到上面没有得到我们想要的结果是因为运算符号的优先级的问题,那么我们可以使用一个括号来解决这个问题:

这样是不是就没有问题了呢?

我们看看下面的代码:

 

我们大家有一开始想着的是对这个数的两倍再乘10吧,但是这个代码的结果并非所愿。

运行结果:

 

那么我们将其替换进去看看这个式子实际上是咋样的:

10*5+5,可以发现其也是因为运算的优先级导致的问题,此时我们是希望这个宏的结果先算出来,然后再乘10,那么我们就使用括号,改变其运算的顺序。

如下:

 

那么此时就得到我们想要的结果了。

四、带有副作用的宏参数 

 以前我们使用宏的时候可能就不知道宏参数有副作用,现在我们来好好学习一下这个知识。

带有副作用的宏参数,也就是我们在使用这个宏的时候,其可能会带来一些问题,导致我们意料之外的事情发生,不过这个副作用主要是后面的内容的部分导致的,其就是表达式求值的时候出现的永久性效果。

下面我们通过一个例子看看:

我们看上面的两个宏,在后面的内容上其表达的意思好像是一样的,但是x++,是会导致x的值发生永久改变的,然后x+1这个就对x的值没有影响。

下面我们再通过一个例子来看:

那么这个代码的运行情况是咋样的呢?我们首先就是a和b先进入这个宏,然后这个宏的语句完成后,然后a++和b++,那么此时我们认为的结果是a为6,b为3,ret为5。那么我们运行看其结果:

可以看到其结果并不是这样,那么我们具体分析一下吧,我们将进替换进去:

((a++)>(b++)?(a++):(b++));

我们将其替换进去后可以看到为啥了,首先是第一个表达式,a和b进行比大小后,进行++,然后这个结果是1,那么就执行a++,导致a进行了两次++,就使得a的值为7了,然后就进行了一次++,那么其结果就是3了,还有就是对于ret的值,其在比完大小后a此时是6,然后整个表达式的结果是第二个语句,其此时是后置++,那么就是6。

那么ret就是6了。

所以我们在使用宏的时候,最好不要使用++和--操作,不过,我们在使用宏的时候,可以先替换看看其是否可以实现我们需要达到的效果。

五、宏替换规则

我们在程序中使用宏和#define符号的时候,需要涉及到下面的几个步骤:

1、在调用宏的时候,首先会对参数进行检查,看其是否包含任何由#define定义的符号,如果有那么其会首先被替换掉。

2、替换文本随后被插入到程序中原来文本的位置,不做任何的更改,而对于宏,参数名被它们的值所替换。

3、最后,再次对结果文件进行扫描,看其是否包含任何由#define定义的符号,如果是,那么就会在进行上述的操作,直到其没有包含#define定义的符号。

我们使用宏还需要注意下面几点:

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

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

六、宏和函数的对比

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

关于聊天室数据库建表

首先了解一下外键 ​​一、外键的本质​​ ​​定义​​:外键是某个表中的字段(或字段组合),其值必须与另一张表的主键值相匹配。 ​​核心作用​​:强制数据一致性,维护表间关系。 二、外键的核心用途…

基于 OpenHarmony 5.0 的星闪轻量型设备应用开发-Ch1 开发环境搭建

写在前面: 文本所写的工程创建均是基于 HH-SPARK-WS63 星闪无线模组。 此篇是系列文章《基于 OpenHarmony5.0 的星闪轻量型设备应用开发》的第 1 章。 1.1 介绍 HH-SPARK-WS63 星闪无线模组(以下简称 WS63)是由润和软件推出的基于海思 WS63V…

离线安装 nvidia-docker2(nvidia-container-toolkit)

很多时候大家都有用docker使用gpu的需求,但是因为网络等原因不是那么好用,这里留了一个给ubuntu的安装包,网络好的话也提供了在线安装方式 安装 nvidia-docker2 1 离线安装 (推荐) unzip解压后进入目录 dpkg -i *.d…

第7篇:Linux程序访问控制FPGA端LEDR<五>

Q:如何设计.c程序代码实现FPGA端外设LEDR流水灯? A:在DE1-SoC开发板上实现的流水灯效果:一次只点亮一个红色LED,初始状态为向左移动直至点亮LEDR9,然后改变移动的方向为向右直至点亮LEDR0,以此…

Unity 实现伤害跳字

核心组件: Dotween TextMeshPro 过程轨迹如下图: 代码如下: using System.Collections; using System.Collections.Generic; using DG.Tweening; using TMPro; using UnityEngine; using UnityEngine.Pool;public class …

008二分答案+贪心判断——算法备赛

二分答案贪心判断 有些问题,从已知信息推出答案,细节太多,过程繁杂,不易解答。 从猜答案出发,贪心地判断该答案是否合法是个不错的思路,这要求所有可能的答案是单调的(例:x满足条件…

衣橱管理助手系统(衣服推荐系统)(springboot+ssm+vue+mysql)含运行文档

衣橱管理助手系统(衣服推荐系统)(springbootssmvuemysql)含运行文档 该系统名为衣橱管理助手,是一个衣物搭配管理系统,主要功能包括衣物档案管理、衣物搭配推荐、搭配收藏以及套装智能推荐。用户可以通过系统进行衣物的搭配和收藏管理,系统提…

文件上传做题记录

1,[SWPUCTF 2021 新生赛]easyupload2.0 直接上传php 再试一下phtml 用蚁剑连发现连不上 那就只要命令执行了 2,[SWPUCTF 2021 新生赛]easyupload1.0 当然,直接上传一个php是不行的 phtml也不行,看下是不是前端验证,…

Vue环境搭建:vue+idea

目录 第一章、Vue环境搭建:安装node2.1)node的下载2.2)配置node的环境变量2.3)常见的npm命令 第二章、使用idea创建vue工程2.1)在IDEA中设置国内镜像2.2)在IDEA中进行脚手架安装2.3)在IDEA中创建…

银河麒麟v10(arm架构)部署Embedding模型bge-m3【简单版本】

硬件 服务器配置:鲲鹏2 * 920(32c) 4 * Atlas300I duo卡 参考文章 https://www.hiascend.com/developer/ascendhub/detail/07a016975cc341f3a5ae131f2b52399d 鲲鹏昇腾Atlas300Iduo部署Embedding模型和Rerank模型并连接Dify(自…

轻量级碎片化笔记memos本地NAS部署与跨平台跨网络同步笔记实战

文章目录 前言1. 使用Docker部署memos2. 注册账号与简单操作演示3. 安装cpolar内网穿透4. 创建公网地址5. 创建固定公网地址 推荐 ​ 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。 点击跳转到网站 前言…

【C++算法】54.链表_合并 K 个升序链表

文章目录 题目链接:题目描述:解法C 算法代码: 题目链接: 23. 合并 K 个升序链表 题目描述: 解法 解法一:暴力解法 每个链表的平均长度为n,有k个链表,时间复杂度O(nk^2) 合并两个有序…

EG8200Mini-104边缘计算网关!聚焦IEC104协议的工业数据转换与远程运维平台

在工业自动化和信息化融合不断深化的背景下,现场设备的数据采集与协议转换能力对系统集成效率与运维成本产生着直接影响。EG8200Mini-104边缘计算网关正是基于此需求场景设计,具备IEC104主从站双向支持能力,并配套远程运维与多网络接入方案&a…

python多线程+异步编程让你的程序运行更快

多线程简介 多线程是Python中实现并发编程的重要方式之一,它允许程序在同一时间内执行多个任务。在某些环境中使用多线程可以加快我们代码的执行速度,例如我们通过爬虫获得了一个图片的url数组,但是如果我们一个一个存储很明显会非常缓慢&…

各种场景的ARP攻击描述笔记(超详细)

1、ARP报文限速 上一章我们说过ARP报文也是需要上送CPU进行处理的协议报文,如果设备对收到的大量ARP报文全部进行处理,可能导致CPU负荷过重而无法处理其他业务。因此,在处理之前需要对ARP报文进行限速,以保护CPU资源。 1.根据源MAC地址或源IP地址进行ARP限速 当设备检测到某一…

庙算兵推:使用Streamlit框架构建了一个智能作战推演系统。

这段代码是一个完整的军事模拟应用,使用Streamlit框架构建了一个智能作战推演系统。该系统包括了三维地图显示、作战单位管理、应急事件处理等功能。用户可以通过界面控制推演的开始和暂停,调整时间加速倍率,并查看实时的战斗情况和系统状态。…

HDCP(四)

HDCP驱动开发实战深度解析 以下从协议栈架构、核心模块实现、安全设计到硬件集成,结合HDCP 2.x规范与主流硬件平台(如ARM、FPGA)特性,系统拆解驱动开发关键环节: 1. 协议栈架构与模块划分 驱动分层设计 硬件抽象层&…

Docker MySQL的主从同步 数据备份 数据同步 配置文件

创建主库 docker run \--namemysql_1 \-e MYSQL_ROOT_PASSWORD123456 \-p 3306:3306 \-v mysql_main_data:/var/lib/mysql \--restart unless-stopped \-d \mysql:8.0进入容器内部 docker exec -it mysql_1 bash查找配置文件 find / -name my.cnf复制出主机 docker cp mysql…

996引擎-疑难杂症:Ctrl + F9 编辑好的UI进入游戏查看却是歪的

Ctrl F9 编辑好UI后,进入游戏查看却是歪的。 检查Ctrl F10 是否有做过编辑。可以找到对应界面执行【清空】

JQuery初步学习

文章目录 一、前言二、概述2.1 介绍2.2 安装 三、语法3.1 文档就绪3.2 选择器 四、事件4.1 概述4.2 事件绑定/解绑4.3 一次性事件4.4 事件委托4.5 自定义事件 五、效果5.1 隐藏/显示5.2 淡入淡出5.3 滑动5.4 动画 六、链七、HTML7.1 内容/属性7.2 元素操作7.3 类属性7.4 样式属…