views:

352

answers:

3

Hi, I'm trying to do something that is conceptually similar to this, but can't seem to get it to work (error shown at end) any ideas?

#include <stdio.h>

int main( int argc , char const *argv[] )
{
  int abc_def_ghi = 42;
  #define SUFFIX ghi
  #define VAR(prefix) prefix##_def_##SUFFIX
  printf( "%d\n" , VAR(abc) );
  return 0;
}

// untitled:8: error: ‘abc_def_SUFFIX’ undeclared (first use in this function)
+8  A: 

You just need additional indirection:

#include <stdio.h>

int main( int argc , char const *argv[] )
{
  int abc_def_ghi = 42;
  #define SUFFIX ghi
  #define VAR3(prefix, suffix) prefix##_def_##suffix
  #define VAR2(prefix, suffix) VAR3(prefix, suffix)
  #define VAR(prefix) VAR2(prefix, SUFFIX)
  printf( "%d\n" , VAR(abc) );
  return 0;
}

Even though it looks redundant, it's not.

caf
Could you explain why?
liori
It's a bit too late for me to try and understand the Standardese for `6.10.3.3 The ## operator`, but it explains why somewhere there. ( pdf @ http://www.open-std.org/JTC1/sc22/wg14/www/docs/n1401.pdf )
pmg
Because the replacement list of a macro is not itself subject to macro-replacement before its parameters are replaced and # and ## operators applied. So in the questioner's code, `def_##SUFFIX` is replaced with `def_SUFFIX` before any opportunity to replace `SUFFIX` with `ghi`. In caf's code, when `suffix` is replaced by `SUFFIX` in VAR2, the argument is first subject to macro expansion (6.10.3.1/1). The result is `VAR3(abc,ghi)`, which yields `abc_def_ghi`. Note that `VAR3(abc,SUFFIX)` would still give `abc_def_SUFFIX`, because parameters following ## are not expanded (also 6.10.2.1/1).
Steve Jessop
"(also 6.10.2.1/1)" - I mean "(also 6.10.3.1/1)".
Steve Jessop
+3  A: 

The usual idiom for correctly using the stringizing (#) or token pasting (##) pre-processing operators is to use a 2nd level of indirection. (http://stackoverflow.com/questions/216875/in-macros/217181#217181).

#define STRINGIFY2( x) #x
#define STRINGIFY(x) STRINGIFY2(x)

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

Then:

int main( int argc , char const *argv[] )
{
  int abc_def_ghi = 42;
  #define SUFFIX ghi
  #define VAR(prefix) PASTE( prefix, PASTE( _def_, SUFFIX))
  printf( "%d\n" , VAR(abc) );
  return 0;
}

Should give you the results you're looking for.

Basically, what happens is that processing of the # and ## operators takes place before macro replacement. Then another round of macro replacement occurs. So if you want macros to be used along with those operations you have to use a 1st level that simply does the replacement - otherwise the stringizing or pasting happens first, and the macros aren't macros anymore- they're whatever the 1st round of stringizing/pasting produces.

To put it more directly - the first level of macro allows the macro parameters to be replaced, then the 2nd level of macro replacement does the stringify/token-pasting operation.

Michael Burr
Wow, thank you, the STRINGIFY also solves another issue I've had.
Joshua Cheek
A: 

This works with sufficient levels of indirection. While another answer is plenty adequate, I want offer this chunk of code as a demo:

#define SUFFIX ghi

#define VAR1(prefix) prefix##_def_##SUFFIX
VAR1(abc)

#define VAR2_(prefix, sfx) prefix##_def_##sfx
#define VAR2(prefix) VAR2_(prefix,SUFFIX)
VAR2(abc)

#define VAR3_(prefix, sfx) prefix##_def_##sfx
#define VAR3x(prefix,sfx) VAR3_(prefix,sfx)
#define VAR3(prefix) VAR3x(prefix,SUFFIX)
VAR3(abc)

Save this is a text file, x.c, and only preprocess it.

gcc -E x.c

Observe and ponder. I don't quite understand it entirely myself. Just spend two hours trying to get a macro using stringify to work. It is interesting to see that double indirection is sometimes needed.

DarenW
I getabc_def_SUFFIXabc_def_SUFFIXabc_def_ghiBased on Steve's explanation, it sounds like it has to do with the order of macro replacement.
Joshua Cheek