我正在尝试将宏调用与令牌连接以创建一个新的,例如:
#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