当前位置: 首页 > news >正文

关于#define的一些小知识

目录

一,#define的声明格式:

二,#define宏的作用是为了完成替换

#define的替换规则:   

三,#define使用时常犯的错误

四,宏与函数的比较

4.1,什么时候使用宏?

4.1,使用宏的好处与坏处

4.3宏的奇怪用法


一,#define的声明格式:

#define name( parament-list ) stuff

关于#define格式需要注意的几个点:

1.在stuff后面不能有冒号

2.name要和左圆括号紧贴在一起

 🌰:使用#define定义一个 求两者间较大值的宏:

#define MAX(a,b) a>b?a:b

二,#define宏的作用是为了完成替换

#define的替换规则:   

1. 在调用宏时,首先对参数进行检查,看看是否包含任何由#define定义的符号。如果是,它们首先
被替换。
2. 替换文本随后被插入到程序中原来文本的位置。对于宏,参数名被他们的值所替换。
3. 最后,再次对结果文件进行扫描,看看它是否包含任何由#define定义的符号。如果是,就重复上
述处理过程。

比如以下代码:

#define MAX(a,b) a>b?a:b
#include<stdio.h>
int main() {int a = 10;int b = 5;printf("%d\n", MAX(a, b));
}

在程序预处理的过程中就会变成这样:

#define MAX(a,b) a>b?a:b
#include<stdio.h>
int main() {int a = 10;int b = 5;printf("%d\n",a>b?a:b);//MAX(a,b)直接被替换掉
}

这也就解释了为什么在宏定义语句的末尾为什么不能加 ;(分号),假如我在宏定义后面加了分号:

#define MAX(a,b) a>b?a:b;

那在替换过程中,MAX(a,b)就会被替换成这样:

 a>b?a:b;
#define MAX(a,b) a>b?a:b
#include<stdio.h>
int main() {int a = 10;int b = 5;printf("%d\n",a>b?a:b;);//明显就是一个错误的代码
}

所以我们便不能在宏定义后面随意加上;(冒号)。

三,#define使用时常犯的错误

3.1不加括号:

#define MUL(a,b) a*b //参数不加括号

现在我让a=2+1,b=2+1代入下列代码中:

#include<stdio.h>
#define MUL(a,b) a*b
int main() {int c = MUL(2+1, 2+1);printf("%d\n", c);return 0;
}

结果:5   

但是我们都知道3*3等于9,所以这个代码为什么会错呢?

原因其实很简单,因为宏会直接替换,也就是宏其实是不会计算的。 所以这段宏就会被替换成这样:

#define MUL(2+1,2+1) 2+1*2+1//c=2+1*2+1=5
int main() {int c = MUL(2+1, 2+1);printf("%d\n", c);//c=5return 0;
}

所以结果就变成5了。

在这里做一个小小的改动:

#include<stdio.h>
#define MUL(a,b) (a)*(b)//加两个括号
int main() {int c = MUL(2+1, 2+1);printf("%d\n", c);return 0;
}

于是宏替换就会变成这个样子:

#define MUL(2+1,2+1) (2+1)*(2+1)//c=(2+1)*(2+1)=9
int main() {int c = MUL(2+1, 2+1);printf("%d\n", c);//c=5return 0;
}

输出:9

但是仅仅做到这样有时候是不保险的:

比如:

🌰:

#define MUL(a,b) (a)+(b)

#define MUL(a,b) (a)+(b)
int main() {int c = 10*MUL(3, 3);//计算的值应该是60printf("%d\n", c);return 0;
}

但是:

输出:33

 因为在这里宏替换以后,宏会变成这样:

#define MUL(a,b) (3)+(3)
int main() {int c = 10*(3)+(3);//相当于10*3+3==33printf("%d\n", c);return 0;
}

在这里就有一个解决方案:

#define MUL(a,b) ((a)+(b))//再加一个大括号
int main() {int c = 10*MUL(3, 3);//计算的值应该是60printf("%d\n", c);return 0;
}

这样就可以得到我们想要的60了。

四,宏与函数的比较

4.1,什么时候使用宏?

在这里我们有一个基本的常识:

   1.实现简单的功能时使用宏。

比如:求两个数的较大值

#define MAX(a,b) ((a)>(b)?(a):(b))

2.实现复杂功能时用函数。

4.1,使用宏的好处与坏处

好处:

1.宏在小型程序中执行的时候更加有效率

2.宏是没有类型的,所以调用的时候更加方便

坏处:

1.无法调试

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

 

4.3宏的奇怪用法

比如使用 malloc这个函数:

正常使用:

#include<stdio.h>
#include<stdlib.h>
int main() {int* arr = (int*)malloc(20);if (*arr == NULL) {perror("malloc:");return;
}//使用//关闭free(arr);arr = NULL;return 0;
}

使用宏:

先定义宏:

#define MALLOC(type,nums) (type)malloc(nums*sizeof(type))

然后就可以这样使用:

#include<stdio.h>
#include<stdlib.h>
#define MALLOC(type,nums) (type)malloc(nums*sizeof(type))
int main() {int* arr = MALLOC(int*,20);if (*arr == NULL) {perror("malloc:");return;}//使用//关闭free(arr);arr = NULL;return 0;
}

今天分享完毕。。。。

相关文章:

关于#define的一些小知识

目录 一&#xff0c;#define的声明格式&#xff1a; 二&#xff0c;#define宏的作用是为了完成替换 #define的替换规则&#xff1a; 三&#xff0c;#define使用时常犯的错误 四&#xff0c;宏与函数的比较 4.1&#xff0c;什么时候使用宏&#xff1f; 4.1&#xff0c;…...

rabbitmq普通集群与镜像集群搭建

1.准备三台centos7主机&#xff0c;并关闭防火墙与selinux 2.安装rabbitmq环境必备的Erlang(以下所有操作三台主机均需要执行) 执行以下命令下载配置erlang yum源 curl -s https://packagecloud.io/install/repositories/rabbitmq/erlang/script.rpm.sh | sudo bash使用yum命…...

session和jwt哪个更好

session和jwtsession优点缺点jwt优点缺点总结session 优点 原理简单&#xff0c;易于学习。用户信息存储在服务端&#xff0c;可以快速封禁某个用户。 缺点 占用服务端内存&#xff0c;硬件成本高。多进程&#xff0c;多服务器时&#xff0c;不好同步-需要使用第三方缓存&a…...

基于TPU-MLIR实现UNet模型部署-决赛答辩02

队伍&#xff1a;AP0200023 目录 初赛 一、 模型导出优化 1.1 直接倒出原始模型并转换 1.2 导出模型前处理 1.2.1 导出Resize 1.2.2 导出归一化 1.3导出模型后处理 1.3.1导出 Resize 与 1.3.2导出 ArgMaxout 1.3.3导出特征转RGB 复赛 一、 确定baseline 二、优化模…...

Maven高级-分模块开发依赖管理

Maven高级-分模块开发&依赖管理1&#xff0c;分模块开发1.1 分模块开发设计1.2 分模块开发实现1.2.1 环境准备1.2.2 抽取domain层步骤1:创建新模块步骤2:项目中创建domain包步骤3:删除原项目中的domain包步骤4:建立依赖关系步骤5:编译maven_02_ssm项目步骤6:将项目安装本地…...

《安富莱嵌入式周报》第308期:开源带软硬件安全认证的PLC设计,开源功率计,可靠PID实现,PR2机器人设计文件全开源,智能手表设计WASP-OS

周报汇总地址&#xff1a;嵌入式周报 - uCOS & uCGUI & emWin & embOS & TouchGFX & ThreadX - 硬汉嵌入式论坛 - Powered by Discuz! 视频版&#xff1a; https://www.bilibili.com/video/BV1F24y157QE 《安富莱嵌入式周报》第308期&#xff1a;开源带软…...

代码随想录算法训练营第五十六天 | 583. 两个字符串的删除操作、72. 编辑距离、编辑距离总结

583. 两个字符串的删除操作 动规五部曲 1、确定dp数组&#xff08;dp table&#xff09;以及下标的含义 dp[i][j]&#xff1a;以i-1为结尾的字符串word1&#xff0c;和以j-1位结尾的字符串word2&#xff0c;想要达到相等&#xff0c;所需要删除元素的最少次数。 2、确定递推…...

Sip协议

简介 SIP&#xff08;Session Initiation Protocol&#xff0c;会话初始协议&#xff09;是一个用于建立、更改和终止多媒体会话的应用 层控制协议&#xff0c;其中的会话可以是 IP 电话、多媒体会话或多媒体会议。SIP 是 IETF 多媒体数据和控 制体系结构的核心协议&#xff0…...

RandomAccessFile类 断点续传

文章目录学习链接RandomAccessFile构造方法实现的接口DataOutputDataInputAutoCloseable重要的方法多线程读写同一个文件&#xff08;多线程复制文件&#xff09;代码1代码2断点续传FileUtils学习链接 RandomAccessFile详解 Java IO——RandomAccessFile类详解 java多线程-断点…...

SpringCloud微服务技术栈的注册中心Eureka

文章目录SpringCloud微服务技术栈的注册中心Eureka简介Eureka特点操作步骤环境准备创建Eureka Server注册服务提供方调用服务消费方总结SpringCloud微服务技术栈的注册中心Eureka 简介 在微服务架构中&#xff0c;服务的数量庞大&#xff0c;而且每个服务可能会有多个实例。此…...

Unity最新热更新框架 hybridclr_addressable

GitHub:YMoonRiver/hybridclr_addressable: 开箱即用的商业游戏框架&#xff0c;集成了主流的开发工具。将主流的GameFramework修改&#xff0c;支持Addressable和AssetBundle&#xff0c;已完善打包工具和流程。 (github.com) # 新增GameFramework Addressables 开箱即用 # 新…...

【c语言】一维数组***特性、存储原理

创作不易&#xff0c;本篇文章如果帮助到了你&#xff0c;还请点赞支持一下♡>&#x16966;<)!! 主页专栏有更多知识&#xff0c;如有疑问欢迎大家指正讨论&#xff0c;共同进步&#xff01; 给大家跳段街舞感谢支持&#xff01;ጿ ኈ ቼ ዽ ጿ ኈ ቼ ዽ ጿ ኈ ቼ ዽ ጿ…...

[oeasy]python0133_[趣味拓展]好玩的unicode字符_另类字符_上下颠倒英文字符

另类字符 回忆上次内容 上次再次输出了大红心♥ 找到了红心对应的编码黑红梅方都对应有编码 原来的编码叫做 ascii️ \u这种新的编码方式叫unicode包括了 中日韩字符集等 各书写系统的字符集 除了这些常规字符之外 还有什么好玩的东西呢&#xff1f; 颠倒字符 这个网站可以…...

找凶手,定名次,字符串旋转,杨氏矩阵

1.找凶手问题&#xff1a; //题目名称&#xff1a; //猜凶手 //题目内容&#xff1a; //日本某地发生了一件谋杀案&#xff0c;警察通过排查确定凶手必为4个嫌疑犯的一个。 //以下为4个嫌疑犯的供词&#xff1a; //A说&#xff1a;不是我 //B说&#xff1a;是C //C说&#xff…...

Python 进阶指南(编程轻松进阶):十四、实践项目

原文&#xff1a;http://inventwithpython.com/beyond/chapter14.html 到目前为止&#xff0c;这本书已经教会了你编写可读的 Python 风格代码的技巧。让我们通过查看两个命令行游戏的源代码来实践这些技术&#xff1a;汉诺塔和四人一排。 这些项目很短&#xff0c;并且基于文…...

Redis的五种数据类型及应用场景

Redis是一个开源的key-value数据库。 五种数据类型 String&#xff0c;List&#xff0c; Set&#xff0c;SortedSet&#xff0c;Hash List类型可以存储多个String。 Set类型可以存储不同的String。 SortedSet可以存储String的排序。 Hash可以存储多个key-value对。 String …...

c++List的详细介绍

cList详细使用 write in front 作者&#xff1a; 不进大厂不改名 专栏&#xff1a; c 作者简介&#xff1a;大一学生 希望能向其他大佬和同学学习&#xff01; 本篇博客简介&#xff1a;本文主要讲述了一种新容器list的使用方法&#xff0c;相信你在学了后&#xff0c;能够加深…...

Heap堆的升序排序

在heap堆中&#xff0c;大根堆是一种特殊的堆&#xff0c;它满足下列性质&#xff1a;对于任意一个非叶子节点i&#xff0c;其左右子节点的值均小于等于它本身的值。 在大根堆中&#xff0c;堆顶元素永远是值最大的元素&#xff0c;所以将堆顶元素不断取出来&#xff0c;就相当…...

小程序开发收费价目表

小程序作为一种新兴应用形式&#xff0c;正在逐渐成为企业和个人推广、运营的重要手段。然而&#xff0c;小程序开发的价格因项目规模和复杂程度差异较大&#xff0c;令不少人望而却步。本文将从小程序开发的相关因素入手&#xff0c;探讨小程序开发的价格范围和算法。 一、小…...

Dubbo服务暴露步骤详解

文章目录Dubbo服务暴露步骤详解背景介绍理论知识讲解什么是服务暴露&#xff1f;Dubbo 服务暴露的基本原理操作步骤具体实现环境准备实现服务接口实现服务提供者配置 Dubbo 服务提供者启动服务提供者实现服务消费者配置 Dubbo 服务消费者测试总结Dubbo服务暴露步骤详解 背景介…...

大数据学习栈记——Neo4j的安装与使用

本文介绍图数据库Neofj的安装与使用&#xff0c;操作系统&#xff1a;Ubuntu24.04&#xff0c;Neofj版本&#xff1a;2025.04.0。 Apt安装 Neofj可以进行官网安装&#xff1a;Neo4j Deployment Center - Graph Database & Analytics 我这里安装是添加软件源的方法 最新版…...

【根据当天日期输出明天的日期(需对闰年做判定)。】2022-5-15

缘由根据当天日期输出明天的日期(需对闰年做判定)。日期类型结构体如下&#xff1a; struct data{ int year; int month; int day;};-编程语言-CSDN问答 struct mdata{ int year; int month; int day; }mdata; int 天数(int year, int month) {switch (month){case 1: case 3:…...

逻辑回归:给不确定性划界的分类大师

想象你是一名医生。面对患者的检查报告&#xff08;肿瘤大小、血液指标&#xff09;&#xff0c;你需要做出一个**决定性判断**&#xff1a;恶性还是良性&#xff1f;这种“非黑即白”的抉择&#xff0c;正是**逻辑回归&#xff08;Logistic Regression&#xff09;** 的战场&a…...

成都鼎讯硬核科技!雷达目标与干扰模拟器,以卓越性能制胜电磁频谱战

在现代战争中&#xff0c;电磁频谱已成为继陆、海、空、天之后的 “第五维战场”&#xff0c;雷达作为电磁频谱领域的关键装备&#xff0c;其干扰与抗干扰能力的较量&#xff0c;直接影响着战争的胜负走向。由成都鼎讯科技匠心打造的雷达目标与干扰模拟器&#xff0c;凭借数字射…...

如何在最短时间内提升打ctf(web)的水平?

刚刚刷完2遍 bugku 的 web 题&#xff0c;前来答题。 每个人对刷题理解是不同&#xff0c;有的人是看了writeup就等于刷了&#xff0c;有的人是收藏了writeup就等于刷了&#xff0c;有的人是跟着writeup做了一遍就等于刷了&#xff0c;还有的人是独立思考做了一遍就等于刷了。…...

html-<abbr> 缩写或首字母缩略词

定义与作用 <abbr> 标签用于表示缩写或首字母缩略词&#xff0c;它可以帮助用户更好地理解缩写的含义&#xff0c;尤其是对于那些不熟悉该缩写的用户。 title 属性的内容提供了缩写的详细说明。当用户将鼠标悬停在缩写上时&#xff0c;会显示一个提示框。 示例&#x…...

基于Java Swing的电子通讯录设计与实现:附系统托盘功能代码详解

JAVASQL电子通讯录带系统托盘 一、系统概述 本电子通讯录系统采用Java Swing开发桌面应用&#xff0c;结合SQLite数据库实现联系人管理功能&#xff0c;并集成系统托盘功能提升用户体验。系统支持联系人的增删改查、分组管理、搜索过滤等功能&#xff0c;同时可以最小化到系统…...

Java数值运算常见陷阱与规避方法

整数除法中的舍入问题 问题现象 当开发者预期进行浮点除法却误用整数除法时,会出现小数部分被截断的情况。典型错误模式如下: void process(int value) {double half = value / 2; // 整数除法导致截断// 使用half变量 }此时...

Proxmox Mail Gateway安装指南:从零开始配置高效邮件过滤系统

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐&#xff1a;「storms…...

WPF八大法则:告别模态窗口卡顿

⚙️ 核心问题&#xff1a;阻塞式模态窗口的缺陷 原始代码中ShowDialog()会阻塞UI线程&#xff0c;导致后续逻辑无法执行&#xff1a; var result modalWindow.ShowDialog(); // 线程阻塞 ProcessResult(result); // 必须等待窗口关闭根本问题&#xff1a…...