johnmachan
johnmachan

Reputation: 113

Generating function names with strings using macros in C

I've two functions:

void foo0(int bar);
void foo1(int bar);

I wan't to be able create a macro QUX that will expand to these function names based on another macro BAZ. I tried the following:

#define BAZ 0
#define QUX(x) foo##BAZ(x)

But it did not work since the generated function was fooBAZ(). How can I get it to generate foo0()?

Upvotes: 11

Views: 19330

Answers (5)

Dean Knight
Dean Knight

Reputation: 680

Here is a solution I came up with after reading a bit online. Basically, in order to get the number to show up in the signature you need to stringify the argument. If you stringify an argument, the prescan does not complete which results in your fooBAZ function definition (it did not fully expand)

If you use another macro intermediary it will complete the expansion.

Here is a link that explains further about prescan and the times it is not completed.

// Testing.cpp : Defines the entry point for the console application.
//
#include <stdio.h>

#define BAZ 0

#define QUXdef(x) QUX(x)
#define QUX(x) foo##x()

#define QUXimp(x) DEF(x)
#define DEF(x) foo##x()


//Function Def
void QUXdef(BAZ);

int main(int argc, char* argv[])
{
    foo0();
}

void QUXimp(BAZ)
{
    printf("Hello world\n");
}

NOTE: I included another set of macros for implementing the function. You did not ask for this, but I figured it would be more "complete" if defining and implementing functions was your goal. QUXdef and QUX fulfill your specific needs.

Edit 1:

  • I removed C++-style code from the solution. It was brought to my attention by Jens Gustedt and is a valid critique considering this was tagged as C(My fault for not reading fully).
  • I also removed the ; form the macro itself. It is now supplied by the user instead which is much more readable. This was also a valid critique from Jens Gustedt
  • I took void out of the macro expansion. Instead I let the user define the return type. To me this seems to also allow for more readability.
  • I removed the stdafx statement considering this is for C code and visual studio is less likely to be used by pure C programmers. As it sits, this should be able to be copied and pasted into a file and then compiled by GCC or some other more popular C compiler.

Otherwise, this answer is solid and if you look at the link I provided it explains the need for an intermediary macro to get the proper expansion the Asker is looking for.

Upvotes: 1

Jens Gustedt
Jens Gustedt

Reputation: 78973

Either have an intermediate macro that evaluates once more

#define QUX_0(A) foo ## A
#define QUX_1(A) QUX_0(A)
#define QUX(x) QUX_1(BAZ)(x)

or maybe even simpler with

#define fooBAZ foo0

BTW: your second ## should error out on a conforming compiler. Also don't put ; at the end of a macro definition, it will bite you.

Upvotes: 3

Jeyaram
Jeyaram

Reputation: 9504

#include <stdio.h>

#define ONE 1
#define ZERO 0

#define GLUE_HELPER(x, y) x##y
#define GLUE(x, y) GLUE_HELPER(x, y)

int foo0(int x)
{
    printf("\n foo0...%d\n", x);
}

int foo1(int x)
{
    printf("\n foo1...%d\n",x);
}

int main()
{
   //Calling Function
   GLUE(foo,ZERO)(5);    
   GLUE(foo,ONE)(10);    
   return 0;
}

will works as expected. You have to do string concate in the second level macro expansion.

Upvotes: 9

BLUEPIXY
BLUEPIXY

Reputation: 40155

#define CAT_I(a,b) a##b
#define CAT(a,b) CAT_I(a, b)
#define QUX(x) CAT(foo, BAZ) ## (x)

Upvotes: 10

JeremyP
JeremyP

Reputation: 86691

If there's only two possibilities:

#if BAZ == 0
#define QUX(X) foo0(x)
#else
#define QUX(X) foo1(x)
#endif

Upvotes: 0

Related Questions