C预处理器:用token连接宏调用



我正在尝试将宏调用与令牌连接以创建一个新的,例如:

#define TEST(X) X ## _TEST
#define CONCAT(X) TEST(X) ## _CONCAT
CONCAT(OK);

然后用gcc -E检查输出;我想要得到OK_TEST_CONCAT;,但我得到了一个错误:

error: pasting ")" and "_CONCAT" does not give a valid preprocessing token

如果我删除##,我没有得到错误,但输出是OK_TEST _CONCAT;

这是一个最小的例子,所以这里最简单的是将所有内容组合在一个宏中,但要知道我不可能摆脱对TEST的第一个调用。有没有办法消除这个空间?

感谢

编辑:

好的,从混乱来看,也许我的例子有点最小,这是我的错。下面是一个更合理的用例:

我希望所有的原型在一个特定的头是由PREFIX在头中定义的前缀。

proto.h:

#define EXPAND(X) EXPAND_HELPER(X)
#define EXPAND_HELPER(X) X
#define PROTO(NAME) PREFIX ## NAME

other.h:

#include <proto.h>
#define PREFIX other
int PROTO(test)(int a, int b);
...

我想要的是所有的原型在other.h有这个形式:int other_test(int a, int b);。但实际上它们有这样的形式:int PREFIX_test(int a, int b);。在谷歌搜索后,我发现我需要强制PREFIX重新扫描,所以我尝试了这个:

#define PROTO(NAME) EXPAND(PREFIX) ## NAME

引起了我的疑问。现在,如果我看看@Lundin的答案,我可以调整它来给出我想要的:

解决方案:

#define PROTO(NAME) PROTO_HELPER(PREFIX, NAME)
#define PROTO_HELPER(PREFIX, NAME) PROTO_EXPAND(PREFIX, NAME)
#define PROTO_EXPAND(PREFIX, NAME) PREFIX ## NAME

谢谢!

必须在调用使用##或#的类函数宏之前展开所有预处理器令牌。因为在宏展开之前应用了##或#。在您的情况下,TEST(X)仅将X扩展到TEST(OK),然后预处理器尝试将TEST(OK)_CONCAT粘贴在一起,这将不起作用。对于每次尝试连接令牌,必须首先展开##之前的所有宏,这是通过强制重新扫描/替换的额外帮助宏来完成的。

给定#define TEST(X) X ## _TEST的人为解决方案将是:

#define CONCAT(X) EXPAND_HELPER(TEST(X)) // expands TEST(X) to TEST(OK)

——比;

#define EXPAND_HELPER(X) CONCAT_HELPER(X, _CONCAT) // expands TEST(OK) to OK_TEST

——比;

#define CONCAT_HELPER(X,Y) X ## Y

:

// NOTE: contrived solution, avoid
#define TEST(X) X ## _TEST
#define CONCAT_HELPER(X,Y) X ## Y
#define EXPAND_HELPER(X) CONCAT_HELPER(X, _CONCAT)
#define CONCAT(X) EXPAND_HELPER(TEST(X))
...
int CONCAT(OK) = 1; // becomes int OK_TEST_CONCAT = 1;

一个更简单的解决方案是:

#define CONCAT(X) X ## _TEST ## _CONCAT

相关内容

最新更新