Search code examples
cmacrospreprocessor

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


Solution

  • 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