0
#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?

Guillaume D
  • 2,202
  • 2
  • 10
  • 37
  • hint: https://stackoverflow.com/questions/8283596/whats-the-difference-between-the-macros-define-strx-x-and-define-strx – harper Oct 24 '22 at 14:10
  • Does this answer your question? [What's the difference between the macros "#define STR(x) #x" and "#define STR(x) VAL(x)" with "#define VAL(x) #x"?](https://stackoverflow.com/questions/8283596/whats-the-difference-between-the-macros-define-strx-x-and-define-strx) – the busybee Oct 24 '22 at 14:12

2 Answers2

2

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;
}
AKX
  • 152,115
  • 15
  • 115
  • 172
2

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.

Persixty
  • 8,165
  • 2
  • 13
  • 35