嵌套宏的参数应该当做宏还是普通字符串

C语言宏展开四步流程详解:从参数分离到递归扫描的完整指南 宏是C语言中通过预处理器实现的文本替换机制,其核心原理是在编译前对源代码进行预处理转换。理解宏展开流程对于编写安全可靠的代码至关重要,它能帮助开发者避免因运算符优先级、参数多次求值等常见问题导致的隐蔽错误。从技术价值看,掌握宏展开机制不仅能提升代码调试效率,还能实现泛型编程、条件编译等高级功能,在嵌入式开发、系统编程等对性能和控制力要求高的场景中广泛应用。本文以参数分离、参数替换、递归扫描和特殊运算符处理这四步为核心,结合经典案例,深入解析宏展开的完整流程与常见陷阱,帮助开发者从根本上理解并安全使用这一强大 阅读详情

转载自:http://www.cppblog.com/ownwaterloo/archive/2010/08/08/74219.html

 

/** 问题描述: */

/* 定义一个带参数的宏 */
#define setname(name) test##name

/* 用一段文本作为该宏的参数 */
int setname(1212) = 1212;
/* 该宏会被替换为:
int test1212 = 1212;
*/

/* 现在有另一个宏 */
#define var 326
/* 如何使用让宏var,作为另一个带参数的宏setnaem的参数? 即:
int setname(var) = 326;
被替换为:
int test326 = 326
而不是:
int testvar = 326;
*/

 

 

问题分析

需要注意:
I. 宏是作文本替换
II. 替换的终止条件是:文件中不再含有宏

对第9行的:SET_NAME(1212)
1. 首先根据I和第5行,SET_NAME(1212) 会被替换成:CONNECTION(test,1212)
2. CONNECTION依然是一个宏,根据II,继续替换
3. 根据I和第4行,CONNECTION(test,1212),被替换为 test1212
4. 所以第10行最终会被CPP替换成 "int test1212 = 1212;"

对第12行的:SET_NAME(VAR)
1. 首先根据I和第5行,SET_NAME(VAR)会被替换成:CONNECTION(test,VAR)
2. CONNECTION和VAR依然是一个宏,根据II,继续替换
3. 根据I和第11行,CONNECTION(test,VAR)被替换为CONNECTION(test,326)
4. 再根据I和第4行,CONNECTION(test,326)被替换为test326
5. 所以第12行最终会被CPP替换成 "int test326 = 326;"

对第16行的:SET_NAME(VAR),同第12行,最终会被替换成 test86



 

为什么setname不行?
setname(var) 会被替换成 testvar,而后者不再含有宏,替换终止。

C语言宏嵌套宏定义:原理、陷阱与工程实践指南 宏定义是C/C++预处理器中的核心机制,它通过文本替换实现代码简化和条件编译。其工作原理遵循定义存储、调用时展开、递归展开禁止等规则,确保编译前代码转换的可控性。在工程实践中,宏的价值在于提升代码复用性和实现平台无关的配置,常见于嵌入式系统、操作系统内核及跨平台库的开发场景。然而,当宏定义嵌套宏定义时,例如在宏体内尝试动态生成新的#define指令,会引发预处理器行为的不确定性,这是C语言进阶中一个典型且易错的领域。本文聚焦宏嵌套展开的机制,深入解析其无效性根源,并通过字符串化、令牌拼接等技巧,探讨如何安全 阅读详情

相关推荐

AD9176 双通道高速DAC调试记录

AD9176是一款高性能双通道16位数模转换器,支持高达12.6GSPS采样率,专为多频段无线应用设计。该器件集成8通道15.4Gbps JESD204B接口,支持复数/实数数据输入,每通道最大输入速率达3.08GSPS。关键特性包括:48位高精度NCO、灵活的插值滤波器(最高12倍)、优异的动态性能(SFDR达-83dBc@1.84GHz)以及多芯片同步功能。硬件调试需重点关注时钟配置(建议250M基准时钟)、JESD参数匹配及交流耦合设计。测试指标要求SFDR>55dBc@312MHz,实测值可达65d

universaldata的博客 1489

使用宏作宏参数

为什么80%的码农都做不了架构师?>>> ...

weixin_33738578的博客 328

【ZYNQ驱动双AD9361实战】(一)从官方参考设计到自定义移植

本文详细介绍了如何将ADI官方的单AD9361参考设计移植到ZYNQ平台以驱动双AD9361射频板卡。内容涵盖从环境搭建、官方工程架构解析,到硬件HDL工程修改(包括顶层设计、引脚分配及TCL脚本适配)以及Linux设备树软件配置的全流程实战指南,帮助开发者实现自定义双通道射频收发系统。

weixin_29170327的博客 362

#define定义宏(2)

首先我们应该先了解一下c语言中字符串具有自动连接的特点。注意只有将字符串作为宏参数的时候才可以把字符串放在字符串中。注:这样的连接必须产生一个合法的标识符,否则其结果就是未定义的。1.使用#,把一个宏参数变成对应的字符串。它允许宏定义从分离的文本片段创建标识符。可以把位于它两边的符号合成一个符号。大家好,今天给大家分享两个技巧。下面我们来讲讲这两个技巧。

2403_86949771的博客 657

程序化广告行业(2/89):从程序化广告深挖数据处理技巧

大家好!我一直希望能和大家在技术学习的道路上携手共进,这也是我写这一系列博客的初衷。上次我们一起学习了Python基础的数据处理知识,这次咱们借助一本程序化广告手册,深入挖掘数据处理的更多技巧。这本手册涵盖了程序化广告从概念到技术实现的诸多方面,而其中处处都涉及到数据处理,相信会给我们带来不少收获

yyy173611的博客 4572

spdk + fio测试nvme 设备的性能

fio的测试对象可以是块设备、文件等,在spdk的使用过程中会unbind默认的nvme driver,所以在系统中是看不到nvme块设备的,在spdk中可以通过fio_plugin的方式,将spdk的用户态driver部分的io功能打包成一个ioengine提供给fio使用,可以综合spdk的高性能和fio提供的复杂场景。更多DPDK相关学习资料有需要的可以自行报名学习,免费订阅,永久学习,或点击这里加。这个jobfile是spdk中提供的例子。领取,关注我持续更新哦!2.7 jobfile的例子。

lingshengxiyou的博客 1088

宏函数作为宏的入参

xxxx

zhangyikuaile的博客 335

别光看原理图了!手把手教你用Altium Designer搞定STM32F411最小系统的PCB布局(附电源/晶振/复位电路实战)

本文详细介绍了使用Altium Designer进行STM32F411最小系统PCB布局的实战技巧,涵盖电源分配网络优化、高速信号布线及系统级布局策略。通过规范的工程结构建立、关键设计规则预设和核心电路模块布局,帮助工程师提升PCB设计效率与信号完整性。特别针对STM32最小系统的电源、晶振和复位电路提供了专业解决方案。

weixin_42653691的博客 166

如何使用一个宏的值作为参数传递给另一个宏?

// 宏中的#号是字符串化的意思,就是说把宏参数看成一个字符串。 // 但是考虑另一种需求:我们要字符串化的参数很长,我们想用另外一个宏代替这个参数。 // 这样的话,你字符串化会有问题, // 字符串化的是另一个宏的名字,而不是宏的值。 // 这就出现了本篇要讨论的问题:如何使用一个宏的值作为参数传递给另...

weixin_34174132的博客 1869

05 - GRACE数据处理-球谐展开与球谐综合

GRACE数据处理-球谐展开和综合前面在介绍GRACE相关理论的时候提到过下面的公式,从公式形式上可以看出,面密度变化和球谐系数(CS)之间是能够相互转换的,那这个转化的过程可以称为球谐展开,简单理解就是将全球网格数据转化为球谐系数的过程。而球谐综合可以看作是球谐展开的逆过程,利用球谐系数计算到全球格网分布。

weixin_43339605的博客 1050

innovus:InstPad、CellPad 、module padding、clock cell halo

我正在「拾陆楼」和朋友们讨论有趣的话题,你⼀起来吧?site_num指的是padding的大小以site宽度为单位。

m0_61544122的博客 2019

C/C++ 宏定义、嵌套宏的展开、可变参数宏

只有覆盖宏定义的作用域是从定义处到文件结尾处(与之对比🆚,using、typedef 等的作用域,则与变量定义的作用域相同)对于带参数的宏定义,宏定义内容部分中出现的参数,其前后必须出现分隔符(字母、数字、下划线以外的符号,比如 空格、‘-’ ‘:’ 等) 才会被预处理当做参数,否则会被当做普通字符串原样保留。

imoisture的博客 5933

Python电梯II

输入数据有若干组(最多不超过1000组),每组数据的第一行为四个如题目中所示的整数N,u,d,s,由空格分隔开。第二行为不同楼层需要上下楼的请求, 最多不超过1000个。每个请求的格式为"from-to",其中"from"和"to"为所在楼层和要到达的楼层,保证from!=to。

沐风—云端行者 908

揭秘C语言宏字符串化黑科技:如何用#和##玩转编译期字符串处理

掌握C语言宏定义的字符串化操作,轻松实现编译期字符串处理。通过#和##运算符,详解日志调试、错误码生成等场景的应用技巧,提升代码灵活性与可维护性。方法实用高效,值得收藏。

LogicGlow的博客 456

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

仓颉语言宏(Cangjie Macros)全面解析:从基础到实战

摘要:仓颉宏是一种编译时代码转换机制,实现元编程功能。其核心特性包括编译时执行、语法树操作、多范式支持和类型安全。宏分为基础宏和带参数宏,应用于代码调试、语法扩展和DSL实现。开发需掌握AST节点处理、代码生成工具和错误报告机制,典型案例如异步函数和类装饰器。最佳实践强调透明性、范围限制和性能优化,合理使用可提升开发效率和代码质量。

猫哥 的沉淀、积累、总结。天天学习,好好向上...c/c++,嵌入式 linux,Android,HarmonyOS,AIOT) 1348

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

C语言宏详解

宏基础 宏仅仅是在C预处理阶段的一种文本替换工具,编译完之后对二进制代码不可见。基本用法如下: 1. 标示符别名 #define BUFFER_SIZE 1024 预处理阶段,foo = (char *) malloc (BUFFER_SIZE);会被替换成foo = (char *) malloc (1024); 宏体换行需要在行末加反斜杠\ #define NUMBERS 1,...

ox0080的博客 3739

AVR汇编宏设计实战:从重复代码到可复用宏库

在嵌入式开发中,代码复用与可维护性一直是工程实践的核心议题。汇编语言作为底层编程手段,其宏机制提供了一种编译期代码生成方案,能在不引入额外运行时开销的前提下实现指令序列的模板化展开。通过宏参数传递、条件汇编与嵌套组合,开发者可以将端口操作、寄存器保护、时序控制等高频逻辑封装为模块化单元,大幅降低重复代码带来的维护成本。这种技术尤其适用于AVR单片机等资源受限平台,在精确时序控制、中断服务例程及底层驱动设计中具有不可替代的优势。理解汇编宏的原理与设计方法,不仅能提升老项目的维护效率,也有助于深入理解编译期代码

weixin_34302561的博客 515

深入剖析C语言宏定义中的#操作符(字符串化的隐藏规则大揭秘)

掌握C语言宏定义的字符串化操作,轻松实现代码自动生成与调试信息输出。详解#操作符的核心规则、典型应用场景及避坑技巧,深入揭示预处理器的隐藏机制,提升开发效率,值得收藏。

LiteCompile的博客 385

C 语言宏定义:从基础到进阶应用

宏定义是 C 语言中的预处理指令,通过#define指令为一段代码或某个值定义一个别名(即宏名)。在程序编译前,预处理器会对源代码进行 “宏替换” 操作,将所有宏名替换为其定义的内容。macro_name:宏的名称,命名规则与变量名一致(只能由字母、数字、下划线组成,且不能以数字开头)。:宏替换时要插入的文本,可以是常量、表达式、代码块等。举几个简单示例:// 为字符串定义宏// 为数值定义宏(圆周率)// 为代码块定义宏b+=1;c=3;})#define <宏名> <字符串>

2401_85539384的博客 1209

C语言宏定义字符串拼接避坑指南(90%程序员都踩过的雷区)

掌握C语言中宏定义的字符串拼接技巧,避免常见编译错误。详解##运算符的正确用法、多参数宏的拼接场景及预处理器展开规则,提升代码可读性与稳定性。避坑要点全解析,值得收藏。

QuickTrans的博客 1049

字符串拼接难题一网打尽,C语言宏定义高级技巧全公开

掌握C语言中宏定义的字符串拼接技巧,轻松解决编译期字符串合并难题。适用于日志输出、代码自动生成等场景,通过#与##运算符实现灵活拼接,提升代码可维护性与扩展性,值得收藏。

VarFlow的博客 931

C 语言基础-宏定义(浅谈有参和无参宏定义,宏函数与普通函数的区别)

什么是宏定义?都能用它来做什么?有什么使用注意点?

fanshengle的博客 2537

【嵌入式开发必备技能】:C语言宏定义参数传递的底层机制剖析

掌握C语言宏定义带参数使用技巧,深入剖析预处理机制与高效编程方法,适用于嵌入式开发中的代码优化与复用。揭示参数替换规则与典型应用场景,提升编译效率与可维护性,值得收藏。

BreakNexus的博客 713

引用另一模板的宏_函数模板及宏定义简单聊

函数模板函数模板不是一个具体的函数,编译器不能为其生成可执行代码。定义函数模板后只是一个对函数功能框架的描述,当他具体执行时,将根据传递的实际参数决定其功能。函数模板的定义template //template 关键字 定义模板返回类型 函数名 (形式参数表){... //函数体}注:<> : 表示模板参数(模板类型参数【class /typedef + 自定义合法标识符】和模板非类...

weixin_39519798的博客 604

AVR汇编宏详解:从寄存器操作到模块化设计

嵌入式开发中,底层硬件控制常依赖汇编语言,而寄存器操作繁琐且容易出错。宏提供了一种编译期代码生成机制,能在不影响运行时性能的前提下实现代码复用。宏的原理是在汇编阶段进行文本替换,每次调用展开为完整指令序列,无额外跳转与压栈开销。在AVR汇编中,宏广泛应用于GPIO操作、精确延时、中断现场保护以及模块化库构建,有效提升代码的抽象层级与可维护性。同时,合理的宏设计需注意寄存器冲突与代码膨胀问题。本文围绕AVR汇编宏的核心语法、高级技巧与工程实践经验,展示如何构建可复用、高可靠的汇编代码基础。

weixin_30629653的博客 367
上一篇: 关于csdn一篇文章java c++多态对纠正(红色字体为纠正)
下一篇: 找不到(或者说不存在)install-templates-msvc.bat文件
hellochenlian
博客等级 码龄17年 629粉丝 295原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值