0

我想知道为什么这个宏扩展如此之大。

#define CONCAT_IMPL(A, B) A##B
#define CONCAT(A, B) CONCAT_IMPL(A, B)

#define EAT(...)
#define TEST(ARG) EXPANDED, ARG) EAT(
#define GET_LAST(A, B) B

int result = 0;
result = GET_LAST(CONCAT(TEST, (1)), 2); // result is 2
result = GET_LAST(TEST(1), 2); // result is 2
result = GET_LAST(EXPANDED, 1) EAT(, 2); // result is 1

我想要 GET_LAST(CONCAT(TEST, (1)), 2); 评价值 1。

如果您能告诉我是否可以在 MSVC 上使用它或者是否缺少某些东西,我将不胜感激。

4

1 回答 1

0

C11草案

由最外面的匹配括号界定的预处理标记序列形成了类函数宏的参数列表。列表中的各个参数由逗号预处理标记分​​隔,但匹配内括号之间的逗号预处理标记不分隔参数。

GET_LAST(CONCAT(TEST, (1)), 2)是使用GET_LAST包含两个参数的列表调用宏。一个是CONCAT(TEST, (1)),另一个是2

在确定了调用类函数宏的参数后,将进行参数替换。替换列表中的参数,除非前面有 # 或 ## 预处理标记或后跟 ## 预处理标记(见下文),在其中包含的所有宏都已展开后,将替换为相应的参数。在被替换之前,每个参数的预处理标记都被完全宏替换,就好像它们形成了预处理文件的其余部分一样;没有其他可用的预处理令牌。

第一个参数A没有出现在宏的替换列表中,所以没有对相应的参数做任何事情。第二个参数B出现,因此对应的参数宏展开为2B替换列表中出现的 被展开替换。

于 2020-06-30T08:20:43.860 回答