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)
4
  • 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 ;) Commented Nov 20, 2009 at 1: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). Commented Nov 20, 2009 at 8:42
  • Right, thanks Michael. It's the other way around (removing const) that would make it non-conformant. I'm beginning to like it! Commented Nov 20, 2009 at 9: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. Commented Nov 21, 2009 at 11:45

3 Answers 3

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.

Sign up to request clarification or add additional context in comments.

3 Comments

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 @ open-std.org/JTC1/sc22/wg14/www/docs/n1401.pdf )
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).
"(also 6.10.2.1/1)" - I mean "(also 6.10.3.1/1)".
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.

1 Comment

Wow, thank you, the STRINGIFY also solves another issue I've had.
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.

1 Comment

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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.