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.宏函数的优点,以空间换时间。

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

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

相关文章

基于高云GW5AT-15 FPGA的SLVS-EC桥MIPI设计方案分享

作者&#xff1a;Hello,Panda 一、设计需求 设计一个4Lanes SLVS-EC桥接到2组4lanes MIPI DPHY接口的电路模块&#xff1a; &#xff08;1&#xff09;CMOS芯片&#xff1a;IMX537-AAMJ-C&#xff0c;输出4lanes SLVS-EC 4.752Gbps Lane速率&#xff1b; &#xff08;2&…

【漏洞复现】CVE-2023-29944 Expression Injection

漏洞信息 NVD - cve-2023-29944 Metersphere v1.20.20-lts-79d354a6 is vulnerable to Remote Command Execution. The system command reverse-shell can be executed at the custom code snippet function of the metersphere system workbench. 背景介绍 MeterSphere is…

在VBA中结合正则表达式和查找功能给文档添加交叉连接

在VBA中搜索文本有两种方式可用&#xff0c;一种是利用Range.Find对象&#xff08;更常见的形式可能是Selection.Find&#xff0c;Selection是Range的子类&#xff0c;Selection.Find其实就是特殊的Range.Find&#xff09;&#xff0c;另一种方法是利用正则表达式&#xff0c;但…

AW36518芯片手册解读(3)

接前一篇文章&#xff1a;AW36518芯片手册解读&#xff08;2&#xff09; 二、详述 3. 功能描述 &#xff08;1&#xff09;上电复位 当电源电压VIN降至预定义电压VPOR&#xff08;典型值为2.0V&#xff09;以下时&#xff0c;该设备会产生复位信号以执行上电复位操作&#x…

【mysql】唯一性约束unique

文章目录 唯一性约束1. 作用2. 关键字3. 特点4. 添加唯一约束5. 关于复合唯一约束 唯一性约束 1. 作用 用来限制某个字段/某列的值不能重复。 2. 关键字 UNIQUE3. 特点 同一个表可以有多个唯一约束。唯一约束可以是某一个列的值唯一&#xff0c;也可以多个列组合的值唯一。…

实操给桌面机器人加上超拟人音色

前面我们讲了怎么用CSK6大模型开发板做一个桌面机器人充当AI语音助理&#xff0c;近期上线超拟人方案&#xff0c;不仅大模型语音最快可以1秒内回复&#xff0c;还可以让我们的桌面机器人使用超拟人音色、具备声纹识别等能力&#xff0c;本文以csk6大模型开发板为例实操怎么把超…

SYD881X RTC定时器事件在调用timeAppClockSet后会出现比较大的延迟

RTC定时器事件在调用timeAppClockSet后会出现比较大的延迟 这里RTC做了两个定时器一个是12秒,一个是185秒: #define RTCEVT_NUM ((uint8_t) 0x02)//当前定时器事件数#define RTCEVT_12S ((uint32_t) 0x0000002)//定时器1s事件 /*整分钟定时器事件&#xff0c;因为其余的…

LearnOpenGL学习(碰撞检测,粒子)

完整代码见&#xff1a;zaizai77/OpenGLTo2DGame: 基于OpenGL制作2D游戏 物体本身的数据来检测碰撞会很复杂&#xff0c;一半使用重叠在物体上的更简单的外形来检测。 AABB - AABB 碰撞 AABB代表的是轴对齐碰撞箱(Axis-aligned Bounding Box)&#xff0c;碰撞箱是指与场景基…

SwinTransformer 改进:添加SelfAttention自注意力层

目录 1. SelfAttention自注意力层 2. SwinTransformer SelfAttention 3. 代码 1. SelfAttention自注意力层 Self-Attention自注意力层是一种在神经网络中用于处理序列数据的注意力机制。它通过对输入序列中的不同位置进行关注&#xff0c;来计算每个位置与其他位置的关联程…

c++ ------语句

一、简单语句 简单语句是C中最基本的语句单元&#xff0c;通常以分号&#xff08;;&#xff09;结尾&#xff0c;用于执行一个单一的操作。常见的简单语句类型有&#xff1a; 表达式语句&#xff1a;由一个表达式后面加上分号构成&#xff0c;用于计算表达式的值或者执行具有…

【他山之石】The SVG path Syntax: An Illustrated Guide:SVG 中的 path 语法图解指南

写在前面 本文为我的自学精译专栏《CSS in Depth 2》第 086 篇文章、在介绍 CSS 的 clip-path 属性的用法时作者提到的一篇延伸阅读材料&#xff0c;以图文并茂的形式系统梳理了 SVG path 属性的方方面面。其中最为精彩的是文中列举的大量使用案例。为了方便查找&#xff0c;特…

小型 Vue 项目,该不该用 Pinia 、Vuex呢?

说到 Vue3 的状态管理&#xff0c;我们会第一时间想到 Pinia、Vuex&#xff0c;但是经过很长一段时间的 Vue3 项目开发&#xff0c;我逐渐发现&#xff0c;我们真的有必要用 Pinia、Vuex 这类的状态管理工具吗&#xff1f; 带着这样的疑惑&#xff0c;我首先是想知道一下 Pini…

c4d动画怎么导出mp4视频,c4d动画视频格式设置

宝子们&#xff0c;今天来给大家讲讲 C4D 咋导出mp4视频的方法。通过用图文教程的形式给大家展示得明明白白的&#xff0c;让你能轻松理解和掌握&#xff0c;不管是理论基础&#xff0c;还是实际操作和技能技巧&#xff0c;都能学到&#xff0c;快速入门然后提升自己哦。 c4d动…

EfficienetAD异常值检测之瓷砖表面缺陷检测(免费下载测试数据集和模型)

背景 当今制造业蓬勃发展&#xff0c;产品质量把控至关重要。从精密电子元件到大型工业板材&#xff0c;表面缺陷哪怕细微&#xff0c;都可能引发性能故障或外观瑕疵。人工目视检测耗时费力且易漏检&#xff0c;已无法适应高速生产线节奏。在此背景下&#xff0c;表面缺陷异常…

将Minio设置为Django的默认Storage(django-storages)

这里写自定义目录标题 前置说明静态文件收集静态文件 使用django-storages来使Django集成Minio安装依赖settings.py测试收集静态文件测试媒体文件 前置说明 静态文件 Django默认的Storage是本地&#xff0c;项目中的CSS、图片、JS都是静态文件。一般会将静态文件放到一个单独…

Redis生产实践中相关疑问记录

1. Redis相关疑问 1.1. redis内存使用率100% 就等同于redis不可用吗&#xff1f; 正常使用情况下&#xff0c;不是。 redis有【缓存淘汰机制】&#xff0c;Redis 在内存使用率达到 100% 时不会直接崩溃。相反&#xff0c;它依赖内存淘汰策略来释放内存&#xff0c;确保系统的…

量化交易——RSI策略(vectorbt实现)

本文为通过vectorbt&#xff08;以下简称vbt&#xff09;实现量化交易系列第一篇文章&#xff0c;通过使用vbt实现RSI策略从而熟悉其代码框架。 关于本文所使用数据的说明 由于vbt官方文档提供的入门案例使用的数据是通过其内置的yfinance包获取&#xff0c;在国内无法直接访…

本地摄像头视频流在html中打开

1.准备ffmpeg 和(rtsp-simple-server srs搭建流媒体服务器)视频服务器. 2.解压视频流服务器修改配置文件mediamtx.yml ,hlsAlwaysRemux: yes 3.双击运行服务器。 4&#xff0c;安装ffmpeg ,添加到环境变量。 5.查询本机设备列表 ffmpeg -list_devices true -f dshow -i d…

unipp中使用阿里图标,以及闭坑指南

-----------------------------------------------------点赞收藏才是更新的动力------------------------------------------------- unipp中使用阿里图标 官网下载图标在项目中引入使用注意事项 官网下载图标 进入阿里图标网站 将需要下载的图标添加到购物车中 2. 直接下载…

设计模式の享元模板代理模式

文章目录 前言一、享元模式二、模板方法模式三、代理模式3.1、静态代理3.2、JDK动态代理3.3、Cglib动态代理3.4、小结 前言 本篇是关于设计模式中享元模式、模板模式、以及代理模式的学习笔记。 一、享元模式 享元模式是一种结构型设计模式&#xff0c;目的是为了相似对象的复用…