C语言带参数的宏定义的相关知识汇总(最常用的形式、带标记分隔符##的形式...)

阅读大型C工程代码时,绕不开带参数的宏定义的阅读,所以有必要强化一下这一块的知识。

01-带参数的宏定义最常用的形式

# define S(a,b) a*b
...
...
...
area = S(3,2);

则在编译预处理时area = S(3,2);被展开为:

area = 3 * 2;

02-带标记分隔符##的宏定义

为什么要引入标记分隔符##

在 C 语言的 预处理器中,对于带参数的宏替换,实际上是以标记为单位来替换的。
比如在下面的宏定义:

# define S(a,b) a*b

a*b中,a是一个标记,b也是一个标记,两个标记通过运算符*进行了划分。
在实际展开时,第一个参数名因为与第一个标记相同,所以去替换第一个标记a;第二个参数名因为与第二个标记相同,所以去替换第二个标记b。

又如:

# define S(aaa,bbb) aaa*bbb

aaa*bbb中,aaa是一个标记,bbb也是一个标记,两个标记通过运算符*进行了划分。
在实际展开时,第一个参数名因为与第一个标记相同,所以去替换第一个标记aaa;第二个参数名因为与第二个标记相同,所以去替换第二个标记bbb。
此时

S(su,wenhao)

会展开为:su*wenhao

但是对于下面这个宏定义:

#define S1(aaa, bbb) aaa*bbbk

就出问题了,因为在aaa*bbbk中,两个标记分别为aaa和bbbk(两个标记通过运算符*进行了划分),第一个参数名因为与第一个标记相同,所以去替换第一个标记aaa,第二个参数名因与第二个标记bbbk不相同,所以无法替换,此时:

S(su,wenhao)

的展开结果为:su*bbbk
但其实我们这里想得到的结开结果为su*wenhaok

那么办呢?我们就需要在bbbk之间加一个标记分隔符,这个标记分隔符就是##,即把宏定义写成下面这样就能得到我们想要的结果:

#define S1(aaa, bbb) aaa*bbb##k

## 的用途举例

1. 动态生成变量名

通过宏创建多个变量名:

#define CREATE_VAR(name) int var_##name;
CREATE_VAR(foo)  // 生成 int var_foo;
CREATE_VAR(bar)  // 生成 int var_bar;
2. 动态生成函数

可以用宏来定义多个函数:

#define CREATE_FUNC(name) void func_##name(void) { printf(#name " function called\n"); }
CREATE_FUNC(init)  // 生成 void func_init(void) { printf("init function called\n"); }
CREATE_FUNC(exit)  // 生成 void func_exit(void) { printf("exit function called\n"); }

调用时:

func_init();  // 输出:init function called
func_exit();  // 输出:exit function called

我在实际工程中遇到使用##的例子

在Linux嵌入式驱动开发中,对于设备类的属性的定义用到了带##的宏。

CLASS_ATTR_WO(led_all_control);

这个宏的定义如下:

#define CLASS_ATTR_WO(_name) struct class_attribute class_attr_##_name = __ATTR_WO(_name)

由于分隔符##的存在,所以_name成为一个标记,所以CLASS_ATTR_WO(led_all_control);会被展开为:

struct class_attribute class_attr_led_all_control = __ATTR_WO(led_all_control)

上面这个展开式的右边其实又是一个带参数的宏定义,这里我就不把它展开了,我们这里重点是强调宏标记分隔符##的使用。

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

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

相关文章

音频进阶学习九——离散时间傅里叶变换DTFT

文章目录 前言一、DTFT的解释1.DTFT公式2.DTFT右边释义1) 复指数 e − j ω n e^{-j\omega n} e−jωn2)序列与复指数相乘 x [ n ] ∗ e − j ω n x[n]*e^{-j\omega n} x[n]∗e−jωn复指数序列复数的共轭正交正交集 3)复指数序列求和 3.DTF…

【保姆级】sql注入之堆叠注入

一、堆叠注入的原理 mysql数据库sql语句的默认结束符是以";"号结尾,在执行多条sql语句时就要使用结束符隔 开,而堆叠注入其实就是通过结束符来执行多条sql语句 比如我们在mysql的命令行界面执行一条查询语句,这时语句的结尾必须加上分号结束 select * fr…

我的桌面 1.9.75 | 个性化定制手机桌面,丰富的小组件和主题

我的桌面iScreen是一款万能桌面小组件APP,提供各种高颜值桌面主题与创意小组件自由组合。支持X面板、照片、待办清单、时钟、日历等实用有趣的小组件。拥有超过500种小组件供选择,包括灵动面板、滚动相册等,搭配300多种精美主题和高清壁纸&am…

汽车燃油软件标定测试

油箱测试 确定油箱的参数: 总容积,额定容积,不可用容积等。油泵测试(静态) 分为加油测试,减油测试,1L或者500ml增减; 分别测试油泵的阻值输出,类似: 油量 阻…

07-ArcGIS For JavaScript--隐藏参数qualitySettings(memory和lod控制)

目录 1、综述2、sceneview.qualitySettings2.1、sceneview.qualitySettings.memoryLimit2.2、lodFactor2.3 additionalCacheMemory 3、结论 1、综述 先上重点,SceneView.qualitySettings为隐藏对象参数,该对象的memoryLimit和lodFactor等值,…

信息科技伦理与道德1:研究方法

1 问题描述 1.1 讨论? 请挑一项信息技术,谈一谈为什么认为他是道德的/不道德的,或者根据使用场景才能判断是否道德。判断的依据是什么(自身的道德准则)?为什么你觉得你的道德准则是合理的,其他…

交换机关于环路、接口绑定、链路聚合的相关知识

文章目录 1、对交换机SW-1进行配置,仅允许Host-1通过Ethernet0/0/1接口与Host-3和Host-4通信,Host-2无法与其他主机通信。2、关闭生成树协议,验证环路造成的影响3、关闭生成树协议通过链路聚合实现两条链路正常通信并提高链路可靠性。 内容包…

QEMU网络配置简介

本文简单介绍下qemu虚拟机网络的几种配置方式。 通过QEMU的支持,常见的可以实现以下4种网络形式: 基于网桥(bridge)的虚拟网络。基于NAT(Network Addresss Translation)的虚拟网络。QEMU内置的用户模式网…

(二)当人工智能是一个函数,函数形式怎么选择?ChatGPT的函数又是什么?

在上一篇文章中,我们通过二次函数的例子,讲解了如何训练人工智能。今天,让我们进一步探讨:面对不同的实际问题,应该如何选择合适的函数形式? 一、广告推荐系统中的函数选择 1. 业务目标 想象一下&#x…

CentOS — 目录管理

文章目录 一、目录结构二、切换目录三、查看目录四、创建目录五、复制目录六、剪切目录七、删除目录 目录也是一种文件。 蓝色目录,绿色可执行文件,红色压缩文件,浅蓝色链接文件,灰色其它文件, 点开头的是隐藏文件&…

2025加密风云:行业变革与未来趋势全景透视

引言 2024年是加密行业发展历程中的重要一年,诸多事件和趋势为未来的发展奠定了基础。随着全球政策环境的变化、技术的不断进步以及市场参与者的多样化,加密行业在2025年将迎来新的转型与挑战。这篇文章将从政策、技术、市场、应用以及社会影响等多个角…

什么是.net framework,什么是.net core,什么是.net5~8,版本对应关系

我不知道有多少人和我一样,没学习过.netCore,想要学习,但是版本号太多就蒙了,不知道学什么了,这里解释下各个版本的关系 我们一般开始学习微软的时候,都是开始学习的.netframework,常用的就是4…

tcpdump指南(1)

大家读完觉得有意义记得关注和点赞!!! tcpdump是一种在网络上转储流量的网络工具。 这篇文章服务器作为一些常用命令的指南。如需完整指南, 请参阅手册页,或在 Linux 计算机上。man tcpdump 1 基本选项 帮助摘要&#…

如何利用 ClickHouse 实现高级分析:MySQL 到 ClickHouse 实时数据同步指南

在数据驱动的时代,企业必须依靠先进的数据分析能力来提升竞争力。随着数据量的激增和业务需求的复杂化,传统的关系型数据库已经无法满足高效处理和实时分析的需求。ClickHouse 作为一款高性能的列式数据库,凭借其卓越的查询性能和可扩展性&am…

UniApp | 从入门到精通:开启全平台开发的大门

UniApp | 从入门到精通:开启全平台开发的大门 一、前言二、Uniapp 基础入门2.1 什么是 Uniapp2.2 开发环境搭建三、Uniapp 核心语法与组件3.1 模板语法3.2 组件使用四、页面路由与导航4.1 路由配置4.2 导航方法五、数据请求与处理5.1 发起请求5.2 数据缓存六、样式与布局6.1 样…

MySQL8安装与卸载

1.下载mysql MySQL :: Download MySQL Community Serverhttps://dev.mysql.com/downloads/mysql/ 2.解压mysql安装包 解压到自己定义的目录,这里解压就是安装,解压后的路径不要有空格和中文。 3.配置环境变量 配置环境变量可以方便电脑在任何的路径…

2025.01.02(数据库)

作业:实现以下功能: 1> 创建一个工人信息库,包含工号(主键)、姓名、年龄、薪资。 2> 添加三条工人信息(可以完整信息,也可以非完整信息) 3> 修改某一个工人的薪资&#…

df.groupby()方法使用表达式分组

# 索引值是否为偶数,分成两组 df.groupby(lambda x:x%20).sum() df.groupby(df.index%20).sum() # 同上这两个写法看似相似,确实都基于索引值来进行分组,但在实现方式上有细微的区别: df.groupby(lambda x: x % 2 0) 这种方式通过…

景区自助售卡机与定点酒店的合作双赢之策-景区酒店方案

一、景区与酒店合作资源优势 1. 提升游客体验:游客在规划旅行时,可以一次性解决住宿和景区游览的安排,减少预订环节的繁琐,提供更便捷、顺畅的旅行体验。 2. 增加游客停留时间:通过联合推广,吸引游客在景区…

RK3588+FPGA全国产异步LED显示屏控制卡/屏幕拼接解决方案

RK3588FPGA核心板采用Rockchip RK3588新一代旗舰 级八核64位处理器,支持8K视频编解码,多屏4K输出,可实现12屏联屏拼接、同显、异显,适配多种操作系统,广泛适用于展览展示、广告内容投放、新零售、商超等领域实现各种媒…