1

I have a test program like below.

  #define TEST(A,B)  A
  #define TEST2(A,B) (A,B)
  #define TEST3(A,B) TEST TEST2(A,B)

  int main()
  {
     TEST3(Hello,World)  //This will expand to TEST (Hello,World)
     TEST (hello, World) // This will expand to hello
  }

The TEST3 will expand to "TEST (Hello,World)", but it won't be expanded further using TEST definition. I initially thought it must be due to a space between TEST and TEST2(hello, world) in the TEST3 definition. But the plain invocation of TEST (hello, world) expands properly. Can someone explain what is happening here?

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
chappar
  • 7,275
  • 12
  • 44
  • 57

1 Answers1

2

The word TEST in #define TEST3(A,B) TEST TEST2(A,B) is not a function-like macro invocation because it is not followed by an open parenthesis. When the pre-processor is expanding TEST3(Hello, World), it encounters TEST, finds it is not an invocation of a function-like macro, and outputs it as text; then it processes TEST2(A, B) and that is a macro invocation, so it outputs the corresponding text, which is (Hello,World), and it continues the processing with the open parenthesis. The TEST is gone, never to be preprocessed again.

See C preprocessor and concatenation for a full discussion of macro expansion with quotes from the standard. You might find How to make a char string from a C macro's value of some help, too.

Community
  • 1
  • 1
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • Why in the the case of direct invocation of TEST, it is being treated as function type macro even though there is a space between MACRO name and '('? – chappar Nov 19 '12 at 07:00
  • Because the (absence of) space only matters in the `#define TEST(A,B)` line, not in the invocation. – Jonathan Leffler Nov 19 '12 at 07:04
  • Slightly more detail: the first expansion of `TEST3(Hello,World)` is `TEST TEST2(Hello,World)`. The key point here is that the "first round" of expansion is solely replacing the arguments and any `#` or `##` operators -- NOT expanding any sub-macros. Then preprocessing resumes as if the file now contained those tokens instead of the original; i.e. the final result of `TEST3(Hello,World) bla` is exactly the same as the final result of `TEST TEST2(Hello,World) bla`. Now it is easy to see that `TEST` is processed and done with before we even start to expand `TEST2`. – M.M May 08 '16 at 04:40