1

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; I would want to get 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;

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. 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.

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);
...

What I want is all the prototypes in other.h to have this form: int other_test(int a, int b);. But as it is they have this form: int PREFIX_test(int a, int b);. After googling I found that I needed to force PREFIX to rescan, so I tried this:

#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:

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!

6
  • Why can't you just do #define CONCAT(X) X ## _TEST ## _CONCAT? Commented Dec 8, 2022 at 10:53
  • @Lundin see my edit, you might understand better what I was looking for, that's my bad for being too vague, but I got it from your answer, thanks! Commented Dec 8, 2022 at 19:17
  • Sorry, but the use case for your updated requirements is nonsense. Just write out the source code prefix manually. The user of your code would like to know what the functions are actually named if they are to call them! If you can remember to write some mysterious PROTO macro all over your header, then you can as well remember to write the relevant source code prefix instead. Writing code like this is just obfuscation and it will get you fired if used in a professional setting. Commented Dec 9, 2022 at 7:17
  • The actual macro I use is _ so that prototypes are named like int _(fname)(int a). I agree it's slightly visually annoying but the purpose is that this code is used in an autogenerated context where code might come from a class. So if I have MyClass::doStuff and MySuperClass::doStuf the generator simply produces #define PREFIX MyClass and _(doStuff) will be expanded to MyClass_doStuff so it won't collide with MySuperClass_doStuff. There is also a translation section in the header static int (*doStuff)(int a) = MyClass_doStuff so that the user can call it with the short name. Commented Dec 9, 2022 at 7:40
  • If you autogenerate code you could as well give all identifiers the correct prefix to begin with. As for my comment, people who deliberately obfuscate source code by creating their "private secret macro language" always upsets me. In the vast majority of such cases, any such attempt is the wrong solution to the actual problem and the question that should be asked, is how to solved the actual problem instead. For example how to run a simple text replacement script on a source file in some programming IDE before compiling. Commented Dec 9, 2022 at 8:02

1 Answer 1

1

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. 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 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
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.