Home > Mobile >  use a value of a preprocessor token to create a new token
use a value of a preprocessor token to create a new token

Time:10-25

#include <stdio.h>
#define ONE 1
#define TWO 2
#define OOPS 42

#define DEF_FOO(x) void foo_##x(void){ printf(#x" %d\n",x);}

DEF_FOO(ONE);
DEF_FOO(TWO);
DEF_FOO(OOPS);

int main()
{
    foo_ONE();
    foo_TWO();
    foo_OOPS();
    
    return 0;
}

gives :

ONE 1
TWO 2
OOPS 42

I would like this:

#include <stdio.h>
#define ONE 1
#define TWO 2
#define OOPS 42

#define DEF_BAR(x) void bar_??x??(void){ printf(#x" %d\n",x);}

DEF_BAR(ONE);
DEF_BAR(TWO);
DEF_BAR(OOPS);

int main()
{
    bar_1();
    bar_2();
    bar_42();
    
    return 0;
}

gives :

ONE 1
TWO 2
OOPS 42

or (its does not matter)

1 1
2 2
42 42

Could I use the value of a token? In theory, preprocessor should know its value, does it?

CodePudding user response:

You'll need two levels of macros:

#define ONE 1
#define TWO 2
#define OOPS 42

#define INNER_DEF_BAR(x) void bar_##x(void){ printf(#x" %d\n",x); }
#define DEF_BAR(x) INNER_DEF_BAR(x)

DEF_BAR(ONE);
DEF_BAR(TWO);
DEF_BAR(OOPS);

int main()
{
    bar_1();
    bar_2();
    bar_42();
    
    return 0;
}

expands to

void bar_1(void){ printf("1"" %d\n",1); };
void bar_2(void){ printf("2"" %d\n",2); };
void bar_42(void){ printf("42"" %d\n",42); };

int main()
{
    bar_1();
    bar_2();
    bar_42();

    return 0;
}

CodePudding user response:

And the other way to AKX's solution. It's the same trick but at a different point to give the output:

ONE 1
TWO 2
OOPS 42

#define ONE 1
#define TWO 2
#define OOPS 42

#define BAR_NAME(x) bar_##x
#define DEF_BAR(x) void BAR_NAME(x)(void){ printf(#x" %d\n",(x)); }

DEF_BAR(ONE);
DEF_BAR(TWO);
DEF_BAR(OOPS);

int main()
{
    bar_1();
    bar_2();
    bar_42();
    
    return 0;
}

The 'trick' here is that undecorated uses of x in DEF_BAR are substituted but the #x isn't. So what is passed the BAR_NAME parametric macro is the substitution value of the parameter (1, 2 or 42 as applicable).

PS: I've put x in brackets because it's good practice. On the one hand I can't think of a case that would work with the token pasting other than a plain identifier.

PPS: Am I the only one who thinks ## is better called the token splicing not token pasting operator as is common.

  • Related