简体   繁体   English

C 预处理器:用令牌连接宏调用

[英]C Preprocessor: concatenate macro call with token

I'm trying to concatenate a macro call with a token to create a new one, for instance:我正在尝试将一个宏调用与一个令牌连接起来以创建一个新的,例如:

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

CONCAT(OK);

Then I check the output with gcc -E ;然后我用gcc -E检查 output ; I would want to get OK_TEST_CONCAT;我想得到OK_TEST_CONCAT; but instead I get an error:但我得到一个错误:

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

If I remove ## I get no error but the output is OK_TEST _CONCAT;如果我删除##我没有得到任何错误,但 output 是OK_TEST _CONCAT;

This is a minimal example, so the easiest here would be to combine everything in a single macro, but know that it's impossible for me to get rid of the first call to TEST .这是一个最小的示例,所以这里最简单的方法是将所有内容组合在一个宏中,但要知道我不可能摆脱对TEST的第一次调用。 Is there a way to remove that space?有没有办法删除那个空间?

Thanks谢谢

EDIT:编辑:

Ok so from the confusion maybe my example was a little too minimal, that's my fault.好吧,从混乱来看,也许我的例子有点简单了,那是我的错。 Here is a more plausible use case:这是一个更合理的用例:

I want all the prototypes in a certain header to be prefixed by the PREFIX defined in that header.我希望某个 header 中的所有原型都以该 header 中定义的PREFIX作为前缀。

proto.h:协议.h:

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

other.h:其他.h:

#include <proto.h>

#define PREFIX other

int PROTO(test)(int a, int b);
...

What I want is all the prototypes in other.h to have this form: int other_test(int a, int b);我想要的是other.h中的所有原型都具有这种形式: int other_test(int a, int b); . . But as it is they have this form: int PREFIX_test(int a, int b);但实际上他们有这种形式: int PREFIX_test(int a, int b); . . After googling I found that I needed to force PREFIX to rescan, so I tried this:谷歌搜索后我发现我需要强制PREFIX重新扫描,所以我尝试了这个:

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

which prompted my question.这引发了我的问题。 Now if I look at @Lundin's answer, I can adapt it to give what I want:现在,如果我查看@Lundin 的回答,我可以对其进行调整以提供我想要的内容:

Solution:解决方案:

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

Thanks!谢谢!

All preprocessor tokens must be expanded before a function-like macro using ## or # is called.在调用使用 ## 或 # 的类函数宏之前,必须展开所有预处理器标记。 Because ## or # is applied before macro expansion.因为 ## 或 # 在宏扩展之前应用。 In your case TEST(X) only expands X into TEST(OK) and then the preprocessor attempts to paste TEST(OK) with _CONCAT which won't work.在您的情况下TEST(X)仅将X扩展为TEST(OK) ,然后预处理器尝试将TEST(OK)_CONCAT粘贴,这将不起作用。 For each attempt to concatenate tokens, you must first expand all macros before ##, which is done by extra helper macros that force a rescanning/replacement.对于每次连接标记的尝试,您必须首先在 ## 之前展开所有宏,这是由强制重新扫描/替换的额外辅助宏完成的。

The contrived solution given #define TEST(X) X ## _TEST would be this:给定#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

That is:那是:

// 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;

A much simpler solution would be:一个更简单的解决方案是:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM