【发布时间】:2019-08-13 10:52:13
【问题描述】:
我刚刚注意到一个关于 C++ 中宏参数扩展的有趣的事情。
我定义了 4 个宏;其中 2 个将给定参数转换为字符串,另外 2 个尝试分隔 2 个参数。我用扩展为 , 的宏向它们传递了参数,得到了以下结果:
#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",这意味着宏逗号首先被解包。但是,宏分离变成了1 , 2 + **empty arg**,这意味着宏comma没有被先解包,我想知道为什么?我在 VS2019 中试过这个。
【问题讨论】:
-
幸运的是,实际上没有人需要编写真正的 C 或 C++ 代码,所以这不是很重要。
-
AFAIK,宏是从上到下处理的,但这可能会重复。因此,宏可以扩展为其他宏,然后扩展为其他宏。 ("Blue painting" 可能与这种情况有关。)我做了google "c preprocessor blue painting" 并找到了一些有趣的链接(例如Is the C preprocessor Turing complete?),尽管我没有找到(或看到)我希望的最终解释。
-
... 但是,除此之外,我想强调@SamVarshavchik 的建议:C++ 中的宏是危险的。虽然可能会很好地添加到 C 中,但在 C++ 中,它们可能会引入可怕的影响,因为它们与名称空间完全无关,并且可能会在作者不期望的地方更改代码。 (这件事已经发生在我身上,在我明白这一点之前,它让我有些头疼......)
-
不知道 (a) 标准怎么说,但 CLANG 的行为不同。
String(1 comma 2);给出了“too many arguments”(因为它调用了Quote())和SeparateImpl(1 comma 2);给出了“too few 参数”。调用Separate(1 comma 2);确实扩展为SeparateImpl()的两个参数调用。看起来 VS2019 总是将单个参数视为单个参数(即使它包含逗号)。
标签: c++ c-preprocessor