2

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)
Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Joshua Cheek
  • 30,436
  • 16
  • 74
  • 83
  • `const argv`? First time I see such a thing! The idea seems nice, but I'm not sure I like it: it makes `main` non-conformant and prevents me from doing something I never did ;) – pmg Nov 20 '09 at 01:43
  • 2
    It's not non-conformant. `argv` can be declared as something equivalent to `char* argv[]` (C99 5.1.2.2.1), and adding the `const` there doesn't change anything except what `main()` is allowed to do with it (without a cast). Remember that a pointer to a non-const can be converted to a pointer to a const no problem - right down to the fact that values of those pointers will compare equal (6.3.2.3/2). – Michael Burr Nov 20 '09 at 08:42
  • Right, thanks Michael. It's the other way around (removing `const`) that would make it non-conformant. I'm beginning to like it! – pmg Nov 20 '09 at 09:43
  • Hi, sorry for that distraction, I should have taken that out. When using TextMate, typing main followed by tab fills out a scaffold for the main method, and that is part of it. – Joshua Cheek Nov 21 '09 at 11:45

3 Answers3

11

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
  • 233,326
  • 40
  • 323
  • 462
  • 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 Nov 20 '09 at 01:33
  • 1
    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 Nov 20 '09 at 01:45
  • "(also 6.10.2.1/1)" - I mean "(also 6.10.3.1/1)". – Steve Jessop Nov 20 '09 at 01:46
7

The usual idiom for correctly using the stringizing (#) or token pasting (##) pre-processing operators is to use a 2nd level of indirection. (What are the applications of the ## preprocessor operator and gotchas to consider?).

#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.

Community
  • 1
  • 1
Michael Burr
  • 333,147
  • 50
  • 533
  • 760
0

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
  • 16,549
  • 7
  • 63
  • 102
  • I get abc_def_SUFFIX abc_def_SUFFIX abc_def_ghi Based on Steve's explanation, it sounds like it has to do with the order of macro replacement. – Joshua Cheek Jan 17 '10 at 18:30