宏参数的扩展如何在C ++中工作 [英] How does expansion of the macro parameters work in c++

查看:65
本文介绍了宏参数的扩展如何在C ++中工作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我刚刚注意到了有关C ++中宏参数扩展的一件有趣的事情。

I just noticed an interesting thing about the expansion of the macro parameters in C++.

我定义了4个宏。其中2个将给定参数转换为字符串,另外2个尝试分离2个参数。我通过宏将其传递给参数,该宏扩展为并得到以下结果:

I defined 4 macros; 2 of them turn given parameter into string and another 2 try to separate 2 arguments. I passed them argument with macro which expands into , and got the following results:

#define Quote(x) #x
#define String(x) Quote(x)
#define SeparateImpl(first, second) first + second
#define Separate(pair) SeparateImpl(pair)
#define comma ,

int main(){
Quote(1 comma 2);  // -> "1 comma 2"
String(1 comma 2); // -> "1 , 2"
SeparateImpl(1 comma 2); // -> 1 , 2 + *empty arg*
Separate(1 comma 2);     // -> 1 , 2 + *empty arg*
return 0;
}

因此,我们看到宏字符串变成了 1,2 ,这意味着宏逗号已首先解压。但是,宏Separate变成了 1,2 + **空arg ** ,这意味着宏逗号没有首先被打开包装,我想知道为什么吗?我在VS2019中尝试过此操作。

So, as we see macro String turned into "1 , 2", that means macro comma had been unpacked first. However, macro Separate turned into 1 , 2 + **empty arg**, that means macro comma hadn't been unpacked first and I wonder why? I tried this in VS2019.

推荐答案

#define Quote(x) #x
#define String(x) Quote(x)
#define SeparateImpl(first, second) first + second
#define Separate(pair) SeparateImpl(pair)
#define comma ,

宏调用收益如下:


  • 参数替换(as),如果替换列表中提到一个参数并且该参数不参与粘贴或字符串化,则该参数将被完全扩展,并且替换列表中对该参数的提及被替换

  • 字符串化

  • 粘贴

  • 重新扫描并进一步替换(草稿),结果重新扫描替换列表,在此期间宏的名称标记为扩展无效(涂成蓝色)。

  • Argument substitution (a.s), where if a parameter is mentioned in the replacement list and said parameter does not participate in a paste or stringification, it is fully expanded and said mentions of the parameter in the replacement list are substituted with the result.
  • Stringification
  • Pastes
  • Rescan and further replacement (r.a.f.r.), where the resulting replacement list is rescanned, during which the macro's name is marked as invalid for expansion ("painted blue").

每种情况应该扩大:

Quote(1 comma 2)

a.s。不执行任何操作(仅提及参数是字符串化)。字符串化适用。结果: 1个逗号2

a.s. no action (only mention of parameter is stringification). Stringification applies. Result: "1 comma 2".

String(1 comma 2)

为适用;产生 Quote(1、2)。在r.a.f.r.期间,报价被标识为宏,但参数计数不匹配。这是无效的。但是请参见下文。

a.s. applies; yielding Quote(1 , 2). During r.a.f.r., Quote identified as a macro, but the argument count doesn't match. This is invalid. But see below.

SeparateImpl(1 comma 2)

无效的宏调用。正在使用一个参数调用该宏,但是该宏应具有2。请注意,将逗号定义为一个宏是不相关的;否则,该参数将不可用。

Invalid macro call. The macro is being invoked with one argument, but it should have 2. Note that comma being defined as a macro is irrelevant; at the level of macro invocation you're just looking at the tokens.

Separate(1 comma 2)

为适用;产生 SeparateImpl(1,2)。在r.a.f.r.期间,调用了 SeparateImpl ...该调用是适用,产生 1 + 2

a.s. applies; yielding SeparateImpl(1 , 2). During r.a.f.r., SeparateImpl is invoked... that invocation's a.s. applies, yielding 1 + 2.

我在VS2019中尝试过。
I tried this in VS2019.

我可以一眼看出在2020年之前是VS,墙壁告诉我他们最终将致力于预处理程序合规性。尤其是VS似乎处于一种奇怪的状态,尽管其中带有逗号的标记仍被视为单个参数(就好像参数识别发生在扩展之前但仍会继续应用一样);因此,在这种情况下, 1,2 在您的 String(1逗号2)调用中会很奇怪;即, Quote 1,2 调用,但在这种情况下,它实际上是一个参数。

I could tell from a glance it was VS something before 2020, where the walls tells me they're finally going to work on preprocessor compliance. VS in particular seems to have this strange state in which tokens with commas in them nevertheless are treated as single arguments (it's as if argument identification occurs before expansion but continues to apply or something); so in this case, 1 , 2 would be that strange thing in your String(1 comma 2) call; i.e., Quote is being called with 1 , 2 but in that case it's actually one argument.

这篇关于宏参数的扩展如何在C ++中工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆