为什么在重新扫描期间不替换参数替换? [英] Why are argument substitutions not replaced during rescanning?

查看:108
本文介绍了为什么在重新扫描期间不替换参数替换?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

请考虑以下宏定义和调用:

  #define xx [0] 
#define y )arg

y(x)

此调用扩展为 x [0] (在Visual C ++ 2010,g ++ 4.1,mcpp 2.7.2和Wave上测试)。



为什么?具体来说,为什么不扩展到 x [0] [0]



在宏替换期间,


替换列表中的参数...将被相应的参数替换,其中包含的所有宏已经扩展。在替换之前,每个参数的预处理令牌都是完全宏替换的(C ++ 03§16.3.1/ 1)。


宏调用,我们采取以下步骤:




  • 函数式宏 y x 作为其 arg 参数的参数调用

  • x 在宏中替换为 x [0]
  • 替换列表中的 arg 替换为参数的替换值 x [0]



替换所有参数后的替换列表为 x [0]


替换列表中的所有参数都已替换后,将重新扫描生成的预处理令牌序列...以获取更多宏名称++ 03§16.3.4/ 1)。



如果在替换列表的此扫描期间找到要替换的宏的名称...它不被替换。此外,如果任何嵌套替换遇到要替换的宏的名称,则不会被替换(C ++ 03§16.3.4/ 2)。


重新扫描替换列表 x [0] (请注意,正在替换的宏的名称为 y ):




  • x 类似对象的宏调用

  • x 替换为 x [0]



由于阻止递归的第16.3.4 / 2节中的规则,此时的替换停止。重新扫描后的替换列表为 x [0] [0]



我测试的预处理器说我错了。此外,这个例子是C ++ 0x FCD(在§16.3.5/ 5)的一个更大的例子,它也说预期的替换是 x [0]

为什么在重新扫描过程中不更换 x b $ b

C99和C ++ 0x在引用部分中的含义与C ++ 03相同。解决方案

我相信你引用了关键段落,你刚刚停止太早。 16.3.4 / 2(强调我):


如果在扫描
期间找到要替换的宏名称替换列表(不包括
其余的源文件的
预处理令牌),它不是
替换。此外,如果任何嵌套的
替换遇到
被替换的宏的名称,
它不会被替换。 这些未更改的
宏名称预处理令牌不是
更长的可用于进一步
替换
,即使他们以后
(re)在上下文中检查
宏名称预处理令牌
否则已被替换。


y 的参数替换期间,用 x [0] 替换x 完全宏替换,意味着它在那时重新扫描,并且递归规则捕获 x 。这意味着 x [0] 中的 x 不再有资格进一步替换,包括在重新扫描 y(x)的部分扩展结果。


Consider the following macro definitions and invocation:

#define x x[0]
#define y(arg) arg

y(x)

This invocation expands to x[0] (tested on Visual C++ 2010, g++ 4.1, mcpp 2.7.2, and Wave).

Why? Specifically, why does it not expand to x[0][0]?

During macro replacement,

A parameter in the replacement list...is replaced by the corresponding argument after all macros contained therein have been expanded. Before being substituted, each argument’s preprocessing tokens are completely macro replaced (C++03 §16.3.1/1).

Evaluating the macro invocation, we take the following steps:

  • The function-like macro y is invoked with x as the argument for its arg parameter
  • The x in the argument is macro-replaced to become x[0]
  • The arg in the replacement list is replaced by the macro-replaced value of the argument, x[0]

The replacement list after substitution of all the parameters is x[0].

After all parameters in the replacement list have been substituted, the resulting preprocessing token sequence is rescanned...for more macro names to replace (C++03 §16.3.4/1).

If the name of the macro being replaced is found during this scan of the replacement list...it is not replaced. Further, if any nested replacements encounter the name of the macro being replaced, it is not replaced (C++03 §16.3.4/2).

The replacement list x[0] is rescanned (note that the name of the macro being replaced is y):

  • x is identified as an object-like macro invocation
  • x is replaced by x[0]

Replacement stops at this point because of the rule in §16.3.4/2 preventing recursion. The replacement list after rescanning is x[0][0].

I have clearly misinterpreted something since all of the preprocessors I've tested say I am wrong. In addition, this example is a piece of a larger example in the C++0x FCD (at §16.3.5/5) and it too says that the expected replacement is x[0].

Why is x not replaced during rescanning?

C99 and C++0x effectively have the same wording as C++03 in the quoted sections.

解决方案

I believe you've quoted the crucial paragraph, you just stopped too soon. 16.3.4/2 (emphasis mine):

If the name of the macro being replaced is found during this scan of the replacement list (not including the rest of the source file’s preprocessing tokens), it is not replaced. Further, if any nested replacements encounter the name of the macro being replaced, it is not replaced. These nonreplaced macro name preprocessing tokens are no longer available for further replacement even if they are later (re)examined in contexts in which that macro name preprocessing token would otherwise have been replaced.

So, when x is replaced with x[0] during the parameter substitution of y, it is fully macro replaced, meaning that it is rescanned at that point, and x is caught by the recursion rule. This means that the x in x[0] is no longer eligible for further replacement, including during the rescanning of the partly-expanded result of y(x).

这篇关于为什么在重新扫描期间不替换参数替换?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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