How to change a constant expression to a literal number during preprocessing? (use gcc)

The code like:

void f1(){
    /* ... */
}

void f2(){
    /* ... */
}

int main()
{
    const int n=2;
    USE(f, n)();
    return 0;
}

I hope it can call f2().

if we just define like:

#define PASTE(a,b) a##b
#define USE(a,b) PASTE(a,b)

it will call fn(). So we should define a new macro to change n to 2, like:

#define PASTE(a,b) a##b
#define CHANGE_constexpr_TO_literal(n)  // I don't know how to define
#define USE(a,b) PASTE(a,CHANGE_constexpr_TO_literal(b))

then the expansion of CHANGE_constexpr_TO_literal(n) will be 2 .

Is it possible to define the macro to force a constexpr n to be literal n? How to define it if possible?

Note:

  • I use GCC compiler, so gnu c extensions are available.
  • Only during preprocessing. I know how to do while during compilation. But it doesn’t have to be a macro.
  • Furthermore, is it possible to change a string constant expression to a literal string? And how to do it?

>Solution :

It cannot be done. Preprocessor operates only on tokens before any C grammar rules are applied. Therefore const int n is not even parsed when USE macro is about to be expanded.

The workaround would be defining USE() as a chain of conditional operator selecting an desired function pointer depending on n.

#define USE(f, n) (    \
   (n == 0) ? f ## 0 : \
   (n == 1) ? f ## 1 : \
   (n == 2) ? f ## 2 : \
   NULL)

The advantage of this approach is that if n is a constant expression then the value of USE() is a constant expression as well.

BTW. In standard C the const int n = 2; does not make n a constant expression. Use either a macro or enum:

#define n 2

or

enum { n = 2 };

Leave a Reply