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

7.C语言 宏(Macro) 宏定义,宏函数

目录

宏定义

宏函数

1.注释事项

2.注意事项

宏(Macro)用法

常量定义

简单函数实现

类型检查

条件编译

宏函数计算参数个数

宏定义进行类型转换

宏定义进行位操作

宏定义进行断言

总结


宏定义

#include "stdio.h"
#include "string.h"
#include "stdlib.h"#define MAX 1025 //定义宏int main() 
{system("pause");return EXIT_SUCCESS;
}

宏函数

宏函数通常将一些比较频繁,短小的函数封装为宏函数。减少一些入栈,出栈的时间消耗。

在C语言中,宏(Macro)是预处理器的一种功能,它允许你定义一种简写形式来代替一段特定的代码。宏定义的基本形式如下:

#include "stdio.h"
#include "string.h"
#include "stdlib.h"#define MYADD(x,y) x + y //宏函数int main() 
{int a = 10;int b = 20;printf("a+b = %d\n",MYADD(a,b));system("pause");return EXIT_SUCCESS;
}

运行结果:

宏函数在预处理中做了一个替换 就是将 a 和 b替换成x和y。

宏函数是使用宏定义的函数风格的宏。它们可以像普通函数那样调用,但最终会被预处理器替换成相应的代码,减少入栈,出栈的时间。

1.注释事项

宏函数要保证运算的完整性才能执行,可以查看下面代码处理流程

#include "stdio.h"
#include "string.h"
#include "stdlib.h"#define MYADD(x,y) x + y //宏函数int main() 
{int a = 10;int b = 20;int result = MYADD(a, b) * 10;printf("result = %d\n", result);system("pause");return EXIT_SUCCESS;
}

打印结果

从上面结果来看,10 + 20 * 10 结果是等于300才符合我们预期,这个是运算完整性导致的。就是先乘除后加减问题

这个问题是可以解决的,通过()来处理,

#define MYADD(x,y) ((x) + (y)) //宏函数

2.注意事项

宏函数在一定的程度上会比普通的函数效率高

#include "stdio.h"
#include "string.h"
#include "stdlib.h"#define MYADD(x,y) ((x) + (y)) //宏函数void myAdd(int x,int y) { //x会在栈上定义,y也会 . 所以宏函数会有一定优势return x + y;
}int main() 
{int a = 10;int b = 20;int result = MYADD(a, b) * 10;printf("result = %d\n", result);system("pause");return EXIT_SUCCESS;
}

可以从宏函数,和普通函数对比,一个没有栈的开销,一个有开销。

普通函数会有入栈和出栈时间上的开销

宏(Macro)用法

常量定义

#include "stdio.h"
#include "string.h"
#include "stdlib.h"#define MAX 1024int main() 
{printf("MAX = %d\n", MAX);system("pause");return EXIT_SUCCESS;
}

运行结果

有参数宏

#include "stdio.h"
#include "string.h"
#include "stdlib.h"#define MYADD(x,y) ((x) + (y)) //宏函数int main() 
{int a = 10;int b = 20;int result = MYADD(a, b);printf("result = %d\n", result);system("pause");return EXIT_SUCCESS;
}

运行结果:

宏运算链接符

#include "stdio.h"
#include "string.h"
#include "stdlib.h"#define MAX 100
#define ROW 100
#define GET_MAX(x,y) \
x = x+y;\
y = x+y;int main() 
{int a = 10;int b = 10;GET_MAX(a, b)printf("random %d  %d\n\n", a,b);system("pause");return EXIT_SUCCESS;
}

从上面代码来看\表示链接符号,运行完第一个,就执行第二个

 无参数宏

#include "stdio.h"
#include "string.h"
#include "stdlib.h"#define MAX 100
#define ROW 100
#define RANDOM (-1.0 + 2.0*(double)rand() / RAND_MAX)int main() 
{int v = 10;printf("random %lf\n\n",RANDOM);system("pause");return EXIT_SUCCESS;
}

类型检查

#include "stdio.h"
#include "string.h"
#include "stdlib.h"#define CHECK_TYPE(a) generic((a), \int: printf("int"), \char: printf("char"), \float: printf("float"), \default: printf("other type") \
)int main() 
{int v = 10;//CHECK_TYPE(v);printf("%s", _Generic(v));system("pause");return EXIT_SUCCESS;
}

条件编译

#include "stdio.h"
#include "string.h"
#include "stdlib.h"#define DEBUG#ifdef DEBUG
#define PRINT_DEBUG(fmt, ...) printf(fmt, ##__VA_ARGS__)
#else
#define PRINT_DEBUG(fmt, ...)
#endifint main() 
{int v = 10;char value[] = "达帮主";PRINT_DEBUG("%s\n",value);system("pause");return EXIT_SUCCESS;
}

运行结果:

如果删掉define就不会有打印

宏函数计算参数个数

#define GET_MACRO(_1, _2, _3, _4, NAME, ...) NAME
#define VA_SIZE(...) \GET_MACRO(__VA_ARGS__, 4, 3, 2, 1, 0)#define SHOW_PARAM_COUNT(...) \printf("Number of parameters: %d\n", VA_SIZE(__VA_ARGS__))// 使用
SHOW_PARAM_COUNT(1, 2); // 输出:Number of parameters: 2

宏定义进行类型转换

#define CONTAINER_OF(ptr, type, member) \((type *)((char *)(ptr) - (char *) &((type *)0)->member))

宏定义进行位操作

#define SET_BIT(x, bit) ((x) |= (1 << (bit)))
#define CLEAR_BIT(x, bit) ((x) &= ~(1 << (bit)))
#define FLIP_BIT(x, bit) ((x) ^= (1 << (bit)))
#define GET_BIT(x, bit) (((x) >> (bit)) & 1)

宏定义进行断言

#define ASSERT(expr) \if (!(expr)) { \printf("Assertion failed: %s\n", #expr); \exit(1); \}

总结

1.宏函数要保证运算的完整性。

2.宏函数在一定程度上,会比普通函数效率高,普通函数会有入栈和出栈时间上的开销。

3.通常会吧调用频繁的,短小的函数封装为宏函数。

4.宏函数的优点,以空间换时间。

相关文章:

7.C语言 宏(Macro) 宏定义,宏函数

目录 宏定义 宏函数 1.注释事项 2.注意事项 宏(Macro)用法 常量定义 简单函数实现 类型检查 条件编译 宏函数计算参数个数 宏定义进行类型转换 宏定义进行位操作 宏定义进行断言 总结 宏定义 #include "stdio.h" #include "string.h" #incl…...

4.系统学习-集成学习

集成学习 前言Bias and Variance过拟合&#xff08;overfitting&#xff09;与欠拟合&#xff08;underfitting&#xff09;集成学习为什么有效&#xff1f;Blending 模型集成Stakcing 模型集成Bagging模型集成Bagging 模型集成算法流程&#xff1a;Boosting模型集成作业 前言 …...

Max AI prompt2:

1&#xff0c;prompt1——总体概览 “请根据以下指导原则撰写文献解读&#xff0c;特别关注作者的研究思路和方法论&#xff1a; 1. 研究背景与目的&#xff1a; 概述文章研究的背景&#xff0c;明确研究的主要目的和研究问题。 2. 研究思路&#xff1a; 详细描述作者如何构建…...

[Unity Shader][图形渲染]【游戏开发】 Shader数学基础8 - 齐次坐标

在计算机图形学中,齐次坐标是一种方便计算和表示几何变换的方式。通过将三维空间中的 33矩阵扩展为 44的形式,可以统一表示平移、旋转、缩放等几何变换操作。在本篇文章中,我们将详细解析齐次坐标的定义及其在图形变换中的应用。 什么是齐次坐标? 齐次坐标的核心思想是通过…...

挑战一个月基本掌握C++(第十二天)了解命名空间,模板,预处理器

一 命名空间 假设这样一种情况&#xff0c;当一个班上有两个名叫 Zara 的学生时&#xff0c;为了明确区分它们&#xff0c;我们在使用名字之外&#xff0c;不得不使用一些额外的信息&#xff0c;比如他们的家庭住址&#xff0c;或者他们父母的名字等等。 同样的情况也出现在 …...

python实现根据搜索关键词爬取某宝商品信息

当程序打开淘宝登陆页面后&#xff0c;需要快速手动登录淘宝&#xff0c;如果服务报错&#xff0c;需要重新登录&#xff01; pip安装库 pip install pyquery pip install selenium pip install openpyxl # 代码说明&#xff1a;代码功能&#xff1a; 基于ChromeDriver爬取tao…...

Posison Distribution

泊松分布 (Poisson Distribution) 泊松分布是概率论中的一个重要离散分布&#xff0c;描述单位时间或单位空间内随机事件发生的次数&#xff0c;假设事件是独立的且平均发生率是已知的。 定义 泊松分布的概率质量函数 (PMF) 为&#xff1a; P ( X k ) λ k e − λ k ! , …...

2024年最新多目标优化算法:多目标麋鹿群优化算法(MOEHO)求解ZDT1-ZDT4,ZDT6及工程应用---盘式制动器设计,提供完整MATLAB代码

一、麋鹿群优化算法 麋鹿群优化算法&#xff08;Elephant Herding Optimization&#xff0c;EHO&#xff09;是2024年提出的一种启发式优化算法&#xff0c;它的灵感来自麋鹿群的繁殖过程。麋鹿有两个主要的繁殖季节&#xff1a;发情和产犊。在发情季节&#xff0c;麋鹿群分裂…...

使用Webpack构建微前端应用

英文社区对 Webpack Module Federation 的响应非常热烈&#xff0c;甚至被誉为“A game-changer in JavaScript architecture”&#xff0c;相对而言国内对此热度并不高&#xff0c;这一方面是因为 MF 强依赖于 Webpack5&#xff0c;升级成本有点高&#xff1b;另一方面是国内已…...

Apache RocketMQ 5.1.3安装部署文档

官方文档不好使&#xff0c;可以说是一坨… 关键词&#xff1a;Apache RocketMQ 5.0 JDK 17 废话少说&#xff0c;开整。 1.版本 官网地址&#xff0c;版本如下。 https://rocketmq.apache.org/download2.配置文件 2.1namesrv端口 在ROCKETMQ_HOME/conf下 新增namesrv.pro…...

CMS(Concurrent Mark Sweep)垃圾回收器的具体流程

引言 CMS&#xff08;Concurrent Mark Sweep&#xff09;收集器是Java虚拟机中的一款并发收集器&#xff0c;其设计目标是最小化停顿时间&#xff0c;非常适合于对响应时间敏感的应用。与传统的串行或并行收集器不同&#xff0c;CMS能够尽可能地让垃圾收集线程与用户线程同时运…...

【Linux】Socket编程-UDP构建自己的C++服务器

&#x1f308; 个人主页&#xff1a;Zfox_ &#x1f525; 系列专栏&#xff1a;Linux 目录 一&#xff1a;&#x1f525; UDP 网络编程 &#x1f98b; 接口讲解&#x1f98b; V1 版本 - echo server&#x1f98b; V2 版本 - DictServer&#x1f98b; V3 版本 - 简单聊天室 二&a…...

磁盘结构、访问时间、调度算法

目录 一、什么是磁盘&#xff1f; 二、磁盘分类 1、从磁头分 2、通过盘面分 三、一次磁盘读/写的时间 四、磁盘调度算法 1、先来先到服务算法FCFS 2、最短寻找时间优先SSTF 3、扫描算法&#xff08;SCAN&#xff09; 4、LOOk算法 5、循环扫描算法&#xff08;C-SCAN…...

详解归并排序

归并排序 归并排序的基本概念归并排序的详细步骤1. 分解阶段2. 合并阶段3. 归并排序的递归流程 时间复杂度分析空间复杂度分析算法步骤2-路归并排序代码分析代码讲解1. 合并两个子数组的函数 merge()2. 归并排序函数 mergeSort()3. 打印数组的函数 printArray()4. 主函数 main(…...

45.在 Vue 3 中使用 OpenLayers 鼠标点击播放视频

引言 在 Web 开发中&#xff0c;地图可视化和互动功能是越来越重要的应用场景。OpenLayers 是一个强大的开源 JavaScript 库&#xff0c;用于显示和处理地图数据&#xff0c;支持多种地图服务和交互功能。在这个教程中&#xff0c;我们将介绍如何在 Vue 3 中集成 OpenLayers&a…...

《大话Java+playWright》系列教程初级篇-初识

后续代码会整理开源-大家期待吧&#xff01;&#xff01;&#xff01; 首先讲下为啥不用python&#xff0c;因为不想下载各种安装插件&#xff0c;太麻烦了&#xff0c;好多不兼容。 所以选择了java。 先来讲下什么是playwright&#xff0c;playwright是微软开源自动化测试工…...

05.HTTPS的实现原理-HTTPS的握手流程(TLS1.2)

05.HTTPS的实现原理-HTTPS的握手流程&#xff08;TLS1.2&#xff09; 简介1. TLS握手过程概述2. TLS握手过程细化3. 主密钥&#xff08;对称密钥&#xff09;生成过程4. 密码规范变更 简介 主要讲述了混合加密流程完成后&#xff0c;客户端和服务器如何共同获得相同的对称密钥…...

提示词工程

一、六何分析法快速写出准确的提示词 英文单词中文解释提问时的思考示例Why何故问题的背景&#xff0c;包括为什么做及目标&#xff08;做成什么样&#xff09;最近我们要与某品牌合作推广冲牙器&#xff0c;对方需要我们策划一场营销活动What何事具体是什么事写一个营销策划方…...

基于python网络爬虫的搜索引擎设计

一、毕业设计&#xff08;论文&#xff09;题目&#xff1a;基于网络爬虫的搜索引擎设计 - 基于网络爬虫的搜索引擎设计1 二、毕业设计&#xff08;论文&#xff09;工作自 2022-09-01 起至 2022-10-28 止 三、毕业设计&#xff08;论文&#xff09;内容要求&#xff1a; 主…...

ip-协议

文章目录 1. 网络层2. ip协议2.1 ip协议格式2.2 网段划分基本概念网段划分的两种方式为什么要网段划分&#xff1f;特殊的IP地址IP地址数量不足 2.3 私有IP与公网IP2.4 路由 3. IP的分片与组装为什么要分片与组装&#xff1f;如何分片&#xff1f;如何组装&#xff1f; 1. 网络…...

国防科技大学计算机基础课程笔记02信息编码

1.机内码和国标码 国标码就是我们非常熟悉的这个GB2312,但是因为都是16进制&#xff0c;因此这个了16进制的数据既可以翻译成为这个机器码&#xff0c;也可以翻译成为这个国标码&#xff0c;所以这个时候很容易会出现这个歧义的情况&#xff1b; 因此&#xff0c;我们的这个国…...

Vue3 + Element Plus + TypeScript中el-transfer穿梭框组件使用详解及示例

使用详解 Element Plus 的 el-transfer 组件是一个强大的穿梭框组件&#xff0c;常用于在两个集合之间进行数据转移&#xff0c;如权限分配、数据选择等场景。下面我将详细介绍其用法并提供一个完整示例。 核心特性与用法 基本属性 v-model&#xff1a;绑定右侧列表的值&…...

Golang dig框架与GraphQL的完美结合

将 Go 的 Dig 依赖注入框架与 GraphQL 结合使用&#xff0c;可以显著提升应用程序的可维护性、可测试性以及灵活性。 Dig 是一个强大的依赖注入容器&#xff0c;能够帮助开发者更好地管理复杂的依赖关系&#xff0c;而 GraphQL 则是一种用于 API 的查询语言&#xff0c;能够提…...

srs linux

下载编译运行 git clone https:///ossrs/srs.git ./configure --h265on make 编译完成后即可启动SRS # 启动 ./objs/srs -c conf/srs.conf # 查看日志 tail -n 30 -f ./objs/srs.log 开放端口 默认RTMP接收推流端口是1935&#xff0c;SRS管理页面端口是8080&#xff0c;可…...

select、poll、epoll 与 Reactor 模式

在高并发网络编程领域&#xff0c;高效处理大量连接和 I/O 事件是系统性能的关键。select、poll、epoll 作为 I/O 多路复用技术的代表&#xff0c;以及基于它们实现的 Reactor 模式&#xff0c;为开发者提供了强大的工具。本文将深入探讨这些技术的底层原理、优缺点。​ 一、I…...

ABAP设计模式之---“简单设计原则(Simple Design)”

“Simple Design”&#xff08;简单设计&#xff09;是软件开发中的一个重要理念&#xff0c;倡导以最简单的方式实现软件功能&#xff0c;以确保代码清晰易懂、易维护&#xff0c;并在项目需求变化时能够快速适应。 其核心目标是避免复杂和过度设计&#xff0c;遵循“让事情保…...

Python Ovito统计金刚石结构数量

大家好,我是小马老师。 本文介绍python ovito方法统计金刚石结构的方法。 Ovito Identify diamond structure命令可以识别和统计金刚石结构,但是无法直接输出结构的变化情况。 本文使用python调用ovito包的方法,可以持续统计各步的金刚石结构,具体代码如下: from ovito…...

RSS 2025|从说明书学习复杂机器人操作任务:NUS邵林团队提出全新机器人装配技能学习框架Manual2Skill

视觉语言模型&#xff08;Vision-Language Models, VLMs&#xff09;&#xff0c;为真实环境中的机器人操作任务提供了极具潜力的解决方案。 尽管 VLMs 取得了显著进展&#xff0c;机器人仍难以胜任复杂的长时程任务&#xff08;如家具装配&#xff09;&#xff0c;主要受限于人…...

代码规范和架构【立芯理论一】(2025.06.08)

1、代码规范的目标 代码简洁精炼、美观&#xff0c;可持续性好高效率高复用&#xff0c;可移植性好高内聚&#xff0c;低耦合没有冗余规范性&#xff0c;代码有规可循&#xff0c;可以看出自己当时的思考过程特殊排版&#xff0c;特殊语法&#xff0c;特殊指令&#xff0c;必须…...

Chromium 136 编译指南 Windows篇:depot_tools 配置与源码获取(二)

引言 工欲善其事&#xff0c;必先利其器。在完成了 Visual Studio 2022 和 Windows SDK 的安装后&#xff0c;我们即将接触到 Chromium 开发生态中最核心的工具——depot_tools。这个由 Google 精心打造的工具集&#xff0c;就像是连接开发者与 Chromium 庞大代码库的智能桥梁…...