宏的使用(C语言详解)

news2024/12/24 10:19:15

在写一个代码生成可执行文件的过程需要经过编译和链接,编译又要经过三部:预处理,编译,汇编。

#define定义的变量和宏就是在预处理阶段会处理的。

一个简单的宏定义:

#include<stdio.h>;
#define Max(a,b) a>b?a:b
int main()
{
	int x = 4, k = 9;
	printf("%d", Max(x, k));
}

Max:宏名

a,b:宏参数

a>b?a:b:宏体

宏定义有些类似函数,Max(a,b)会被替换为 a>b?a:b

比如这里printf("%d",Max(x,k));在预处理阶段会被替换为printf("%d",x>k?x:k);

注意:在#define定义的宏或变量后面不能加分号(;)

例如: 

1.运算符优先级处理

思考下面输出结果:

#define Mul(a,b) a*b
int main()
{
	int x = 4, k = 3;
	printf("%d", Mul(x, k + 2));
	return 0;
}

这里printf("%d", Mul(x, k + 2));会被替换为printf("%d",x*k+2);

所以结果为14,注意这里只是一一替换在预处理阶段进行,结果并不是20,而计算阶段是再生成的.exe后缀文件执行以后的事,所有在定义宏的时候,为了达到想要的效果我们通常在宏体里面加一些括号来避免这种问题的出现

例如:

#define Mul(a,b) ((a)*(b))

2.带副作用的宏参数

在给宏传参的时候我们尽量避免传一些前缀或后缀++ --这样的参数,这是一些带有副作用的参数

 例如:

#define Max(a,b) ((a)>(b)?(a):(b))//添加括号是解决优先级带来的潜在问题,上一个板块讲到
int main()
{
	int x = 2, k = 3;
	printf("%d", Max(++x, ++k));
}

程序执行后输出5,这里x变为3,k变为5。结果是我们无法预料的。

3.函数与宏的区别:

4.宏替换的规则

在程序中扩展#define定义符号和宏时,需要涉及⼏个步骤。
1. 在调⽤宏时,⾸先对参数进⾏检查,看看是否包含任何由#define定义的符号。如果是,它们⾸先被替换。
2. 替换⽂本随后被插⼊到程序中原来⽂本的位置。对于宏,参数名被他们的值所替换。
3. 最后,再次对结果⽂件进⾏扫描,看看它是否包含任何由#define定义的符号。如果是,就重复上述处理过程。
注意:
1. 宏参数和#define定义中可以出现其他#define定义的符号。但是对于宏,不能出现递归。
2. 当预处理器搜索#define定义的符号的时候,字符串常量的内容并不被搜索

5.#运算符的使用

#运算符将宏的⼀个参数转换为字符串字⾯量。它仅允许出现在带参数的宏的替换列表中。
#运算符所执⾏的操作可以理解为”字符串化“。
当我们有⼀个变量 int a = 10; 的时候,我们想打印出: the value of a is 10 .
就可以写:
 

#define Print(n) printf("the value of "#n" is %d", n);
int main()
{
	int a = 0;
	Print(a);
	return 0;
}

而写作下面的形式只会打印 the value of n is 10,其中的n并不会被替换

 #define Print(n) printf("the value of n is %d", n);

6.##运算符的使用

## 可以把位于它两边的符号合成⼀个符号,它允许宏定义从分离的⽂本⽚段创建标识符。 ## 被称
为记号粘合
这样的连接必须产⽣⼀个合法的标识符。否则其结果就是未定义的。
这⾥我们想想,写⼀个函数求2个数的较⼤值的时候,不同的数据类型就得写不同的函数
比如:

int int_max(int x, int y)
{
    return x>y?x:y;
}

float float_max(float x, float y)
{
    return x>yx:y;
}

这么写很繁琐我们可以用宏定义来写函数

7.宏定义函数

#define Max(type) type type##_max(type x,type y)\
				  {			\
						return x>y?x:y;	\
				  }
这里\为续行符
Max(int)
Max(float)
Max(char)
int main()
{
	printf("%d\n", int_max(5, 9));
	printf("%.2f\n", float_max(5.2, 5.32));
	printf("%c\n", char_max('p', 'h'));
}

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

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

相关文章

【微服务】SpringCloud之Feign远程调用

&#x1f3e1;浩泽学编程&#xff1a;个人主页 &#x1f525; 推荐专栏&#xff1a;《深入浅出SpringBoot》《java对AI的调用开发》 《RabbitMQ》《Spring》《SpringMVC》《项目实战》 &#x1f6f8;学无止境&#xff0c;不骄不躁&#xff0c;知行合一 文章目录 …

Mac安装Docker提示Another application changed your Desktop configuration解决方案

1. 问题描述 Mac安装Docker后&#xff0c;提示Another application changed your Desktop configuration&#xff0c;Re-apply configurations无效 2. 解决方案 在终端执行下述命令即可解决&#xff1a; sudo ln -sf /Applications/Docker.app/Contents/Resources/bin/docke…

TLF9471 - High-Speed CAN FD Transceiver

1 框图描述 2 功能描述 CAN收发器被设计用来承受汽车应用的恶劣条件,并支持12V应用。   SBC的控制器区域网络(CAN)收发器部分在汽车和工业应用中提供高速(HS)差分模式数据传输(最高可达2Mbaud) 和接收。它作为CAN协议控制器和与ISO 11898-2:2016和SAE J2284兼容的物理…

基于单片机干湿垃圾自动分类系统

**单片机设计介绍&#xff0c;基于单片机干湿垃圾自动分类系统 文章目录 一 概要二、功能设计三、 软件设计原理图 五、 程序六、 文章目录 一 概要 基于单片机的干湿垃圾自动分类系统是一个集成传感器技术、机械控制和单片机编程于一体的自动化解决方案。该系统的主要目标是实…

MS9740B进行DUT插入损耗的评估,操作步骤?

使用MS9740B进行DUT&#xff08;设备待测&#xff09;插入损耗的评估&#xff0c;首先需要了解MS9740B的基本功能和配置。MS9740B是一款高精度光谱分析仪&#xff0c;支持多种光纤类型&#xff0c;包括SM光纤&#xff08;ITU-T G.652&#xff09;和GI光纤&#xff08;50μm/125…

【C++】C++中的list

一、介绍 官方给的 list的文档介绍 简单来说就是&#xff1a; list是可以在常数范围内在任意位置进行插入和删除的序列式容器&#xff0c;并且该容器可以前后双向迭代。list的底层是双向链表结构&#xff0c;双向链表中每个元素存储在互不相关的独立节点中&#xff0c;在节点中…

IO流【带有缓冲区的字节输入、输出流;字符输入、输出流 转换流】

day35 学习注意事项 按照流的发展历史去学习注意流与流之间的继承关系举一反三 IO流 继day36 字节流继承图 字节流 应用场景&#xff1a;操作二进制数据&#xff08;音频、视频、图片&#xff09; abstract class InputStream – 字节输入流的基类&#xff08;抽象类&#xff0…

1、认识MySQL存储引擎吗?

目录 1、MySQL存储引擎有哪些&#xff1f; 2、默认的存储引擎是哪个&#xff1f; 3、InnoDB和MyISAM有什么区别吗&#xff1f; 3.1、关于事务 3.2、关于行级锁 3.3、关于外键支持 3.4、关于是否支持MVCC 3.5、关于数据安全恢复 3.6、关于索引 3.7、关于性能 4、如何…

项目经理想提升,可不止PMP这一个证书!

软考 系统集成项目管理工程师 信息系统项目管理师 中高项知识体系 软考价值&#xff1a; 软考的价值体现在多个方面&#xff1a; 在评职称方面&#xff0c;软考可以为个人提供北京工作居住证、一线城市积分落户等方面的支持&#xff0c;有利于个人在工作和生活中的稳定和发…

Java Netty个人对个人私聊demo

一、demo要求 1&#xff09;编写一个Netty个人对个人聊天系统&#xff0c;实现服务器端和客户端之间的数据简单通讯&#xff08;非阻塞&#xff09; 2&#xff09;实现单人对单人聊 3&#xff09;服务器端&#xff1a;可以监测用户上线&#xff0c;离线&#xff0c;并实现消…

【新手上路】C#联合Halcon第一个demo搭建

前言 学习Halcon目的是能够利用C#封装成一个视觉的上位机应用配合机器人或者过程控制来提高生产的效率&#xff0c;尤其是在检测外观和定位方面的应用。现在我们就来搭建第一个demo。让他们能够跑起来&#xff01; Halcon方面 打开Halcon软件&#xff0c;然后先随便写一个代…

ADW310 导轨式单相无线计量仪表-安科瑞黄安南

ADW310 无线计量仪表主要用于计量低压网络的有功电能&#xff0c;具有体积小、精度高、功能丰富等优点&#xff0c;并且可 选通讯方式多&#xff0c;可支持 RS485 通讯和 Lora、4G 等无线通讯方式&#xff0c;增加了外置互感器的电流采样模式&#xff0c;从而方便 用户在不同场…

uniapp使用npm命令引入font-awesome图标库最新版本

uniapp使用npm命令引入font-awesome图标库最新版本 图标库网址&#xff1a;https://fontawesome.com/search?qtools&or 命令行&#xff1a; 引入 npm i fortawesome/fontawesome-free 查看版本 npm list fortawesome在main.js文件中&#xff1a; import fortawesome/fo…

想在小红书写出数据分析类的爆文?带你分析爆文的写作思路

一、小红书运营分析背景介绍 在如今社交媒体的浪潮中&#xff0c;小红书、抖音、知乎等平台的流量如同滚滚长江&#xff0c;吸引了无数公司和品牌前来淘金。对于想要推广公司的产品和主营业务而言&#xff0c;如何在这些平台上脱颖而出&#xff0c;成为了一大难题。 数据分析&a…

Java文件流操作

一、文件创建和删除 public static void main(String[] args) throws IOException {File file new File("..\\hello-world.txt");//..表示在上机目录下创建hello-world.txtSystem.out.println(file.getPath());//返回当前相对路径System.out.println(file.getCanoni…

小型案例(acl,nat,dns,dhcp,静态路由)

实验目录&#xff1a;内网互通&#xff0c;pc不可以访问外网&#xff0c;server2可以通过外网访问&#xff08;nat技术&#xff09;&#xff0c;pc2&#xff0c;和pc3可以访问外网 拓扑图如下 配置信息如图&#xff0c;pc1~3 和server2 对应vlan分别是10&#xff0c;20&#…

Matlab 修改图例顺序

对于使用 .m 文件绘制的图片&#xff0c;可以修改程序中图例的顺序来改变图片的图例。如果图片所对应的 .fig 文件已经存在&#xff0c;而且不便修改源程序&#xff0c;则可以通过如下方式来修改图例&#xff1a; step 1: 打开fig文件&#xff0c;然后点击绘图浏览器 step 2&…

Qt实现无边框圆角窗口

我们在使用QDialog的时候许多场景下都不需要默认的标题栏&#xff0c;这时候我们需要设置他的标志位。 this->setWindowFlags(Qt::FramelessWindowHint);由于现代的窗口风格&#xff0c;我们一般会设置窗口为圆角边框的样式&#xff0c;我们可以使用qss的方式来进行设置。 …

WebAPI(一)之DOM操作元素属性和定时器

webAPI之DOM操作元素属性和定时器 介绍概念DOM 树DOM 节点document 获取DOM对象操作元素内容操作元素属性常用属性修改控制样式属性操作表单元素属性自定义属性 间歇函数今日单词 了解 DOM 的结构并掌握其基本的操作&#xff0c;体验 DOM 的在开发中的作用 知道 ECMAScript 与 …

鱼骨图功能实现

dom: <div class="module-content"><div class="title"><span>[</span><p>鱼骨图</p><span>]</span></div><div class="line-mian"></div><div :ref="module + i&q…