我正在研究关于C ++预处理器如何处理宏替换的C ++标准(我需要自己实现C ++预处理器的一个子集)。这是我为学习创建的一个例子:
#define a x
#define x(x,y) x(x+a, y+1)
a(x(90, 80), a(1,2))
通过要求VC ++ 2010生成预处理器输出文件,我发现上面的a(x(90, 80), a(1,2))
变成了这个:
90(90+x, 80+1)(90(90+x, 80+1)+x, 1(1+x, 2+1)+1);
但是预处理器如何提出这个输出呢?规则太复杂,无法理解。有人可以解释预处理器为提出这样的结果所做的所有步骤吗?
答案 0 :(得分:6)
旧答案,顺序不准确(见编辑):
让我们从你的表达开始:
a(x(90, 80), a(1, 2))
现在,由于我们有
#define a x
,它会扩展为:x(x(90, 80), x(1, 2)) // ^^^^^^^^^ ^^^^^^^ // arg 'x' arg 'y'
我们可以应用
x(x,y)
的定义,即#define x(x,y) x(x+a, y+1)
:x(90, 80)(x(90, 80)+a, x(1, 2)+1)
还有另一个会传播
x(...)
。你还可以注意到+a
那个>之前的表达式已扩展为+x
:90(90+a, 80+1)(90(90+a, 80+1)+x, 1(1+a, 2+1)+1) // ^^ // expanded
上次:剩余的
+a
已扩展为+x
:90(90+x, 80+1)(90(90+x, 80+1)+x, 1(1+x, 2+1)+1) // ^^ ^^ ^^ // expanded expanded expanded
我希望没有错误。
请注意,您对x(x,y)
的定义非常含糊(对于人类而言):宏名称和参数共享相同的名称。请注意,即使没有,宏也不是递归的,所以如果你有
#define x(u,v) x(u+a, b+1)
它不会扩展为类似
的东西x(u+a+a+a+a, b+1+1+1+1)
这是因为当定义宏x
时,其名称对内部宏定义不是“可用的”。
另一个小注意事项:对于gcc,输出不完全相同,因为gcc在替换的标记之间添加空格(但如果删除它们将与msvc相同)。
编辑 :根据dyp的评论,此订单不是确切的顺序。实际上,首先展开参数,然后在宏表达式中替换。句子的最后一部分很重要:这意味着不重新评估宏参数列表。可以把它想象成:使用占位符代替参数扩展宏,然后扩展参数,然后用各自的参数替换占位符。所以,简而言之,这相当于我之前解释过的,但这里是正确的顺序(详细操作):
> Expansion of a(x(90, 80), a(1, 2))
> Substitution of 'a' into 'x' (now: 'x(x(90, 80), a(1, 2))')
> Expansion of x(x(90, 80), a(1, 2)) [re-scan]
> Macro 'x(X, Y)' is expanded to 'X(X+a,Y+1)'
> Expansion of 'x(90,80)' (first argument)
> Macro 'x(X,Y)' is expanded to 'X(X+a,Y+1)'
> Argument '90' does not need expansion (ie, expanded to same)
> Argument '80' does not need expansion (ie, expanded to same)
> Substitution with 'X=90' and 'Y=80': '90(90+a, 80+1)'
> Re-scan of result (ignoring macro name 'x')
> Substitution of 'a' into 'x': '90(90+x, 80+1)'
> Expansion of 'a(1,2)' (second argument)
> Substitution of 'a' into 'x'
> Expansion of 'x(1,2)' [re-scan]
> Macro 'x(X,Y)' is expanded to 'X(X+a,Y+1)'
> Argument '1' does not need expansion (ie, expanded to same)
> Argument '2' does not need expansion (ie, expanded to same)
> Substitution with 'X=1' and 'Y=2': '1(1+a, 2+1)'
> Re-scan of result (ignoring macro name 'x')
> Substitution of 'a' into 'x': '1(1+x, 2+1)'
> Substitution with X='90(90+x, 80+1)' and Y='1(1+x, 2+1)'
Result: '90(90+x, 80+1)(90(90+x, 80+1)+a, 1(1+x, 2+1)+1)'
> Re-scan of result
> Substitution of 'a' into 'x'
Result: '90(90+x, 80+1)(90(90+x, 80+1)+x, 1(1+x, 2+1)+1)'
Last result is result of whole expansion:
90(90+x, 80+1)(90(90+x, 80+1)+x, 1(1+x, 2+1)+1)