VS中 宏 的使用,做个小小的总结,以及常见的一些疑问

本文探讨了在Visual Studio中宏的使用,解释了`#`和`##`的含义,以及宏替换的规则。通过示例说明了宏替换的过程,强调了`#`会导致参数转义为字符串,而`##`用于连接参数。文章解答了为何在调试宏中需要使用#define DEBUG1(x,y) DEBUG2(x,y),以确保__FILE__和__LINE__能够正确替换为它们的变量值。" 88350427,8174935,软件质量模型详解:六大特性与扩展,"['软件工程', '质量保证', '用户体验', '系统性能', '软件设计']

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 我们经常在阅读其他人写的代码中看到这样的代码:


#define DEBUG2(x,y) "Line " #y " of File " x
#define DEBUG1(x,y) DEBUG2(x,y)
#define LINE_FILE DEBUG1( __FILE__ , __LINE__ )

我总是疑惑,为什么还需要#define DEBUG1(x,y) DEBUG2(x,y)这个呢? 直接用DEBUG2(x,y)不好么? 如果你也有相同的疑惑,那么咱们一起来探索下:


先说下宏中#和##分别代表的含义:

#代表将紧随其后的参数转义成字符串;##的含义是将两个“东西”(后面说 东西 含义)连接起来;注意,#是用做参数处理的,不能用于一般的处理;而##是可以用于一般的字符串或者变量和字符串或者变量和变量的连接,这也是在前面说东西的具体所指。

先看下面的一段示例:


#include <stdio.h>
#define f(a,b) a##b
#define g(a)   #a
#define h(a) g(a)
 
int main()
{
        printf("%s\n", h(f(1,2)));
        printf("%s\n", g(f(1,2)));
        return 0;
}

然后再看这两个输出,顺序从左向右替换,第一个宏首先将h(f(1,2))替换成g(f(1,2)),然后就该将f(1,2)替换成整数12了,此时就是g(12),第一轮替换完成再开始第二轮,继续回到最左边开始,只需一次就变成了"12",此时就是最终结果了。

  第二个宏有点不一样了,还是从左边开始,g(f(1,2))在第一次替换后变成了"f(1,2)",此时就不可替换了,因为原本的宏f此时已经是一个字符串了,所以就此结束。

  因此上面的程序输出是字符串12和字符串f(1,2)。

从以上,我们可以看出宏替换有如下的规则:


1.如果宏定义是以#开头,那么不展开其参数,直接替换;

2.宏替换是从左向右,从外到里的替换,直到碰到以#开头,则停止一轮替换,在第一轮替换完成后再次从左向右进行第二轮替换,以此类推,直到所有替换完成。在替换过程中有一条规则:如下:

在替换列表中的所有参数替换过之后,预处理器将对结果token序列重新扫描以便对其中的宏再次替换。
当正在替换的宏在其替换列表中发现自身时,就不再对其进行替换。今儿,在任何正在嵌套替换的宏的替换过程中遇到正被替换的宏就对其不再进行替换(防止递归)。
例:
#define ROOT AAA CCC
#define AAA ROOT
ROOT
将被替换成
ROOT CCC

3.宏替换遇到###这种情况时,总是##优先于#释义,如A###B的含义是 将B转化成字符串后与A链接;


现在来看看上面提出的问题:

#define DEBUG2(x,y) "Line " #y " of File " x
#define DEBUG1(x,y) DEBUG2(x,y)
#define LINE_FILE DEBUG1( __FILE__ , __LINE__ )

即为什么不能直接

#define LINE_FILE DEBUG2( __FILE__ , __LINE__ )  ???


根据我们上面得到的知识,编译器遇到LINE_FILE时,会将LINE_FILE转换换成

DEBUG1( __FILE__ , __LINE__ )

,再一轮转换成为:

DEBUG2(__FILE__的变量值(注意此处已经替换成变量的值了),__LINE__的变量值(同左))

然后再一次替换便可以得到正确的调试输出语句。


如果只用DEBUG2(__FILE__, __LINE__),那么替换的结果将是:

Line __FILE__ of File  aaa.cpp

__FILE__直接被转换成字符串输出,不会有替换变量值的机会了,因为前面有个#号的缘故(#__FILE__)


小弟新发博客,语句多有不通顺,望大家不要拍我哈,有问题可以给我留言,谢谢!



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值