Why do these blocks of code yield different results?
Some common code:
#define PART1PART2 works
#define STRINGAFY0(s) #s
#define STRINGAFY1(s) STRINGAFY0(s)
case 1:
#define GLUE(a,b,c) a##b##c
STRINGAFY1(GLUE(PART1,PART2,*))
//yields
"PART1PART2*"
case 2:
#define GLUE(a,b) a##b##*
STRINGAFY1(GLUE(PART1,PART2))
//yields
"works*"
case 3:
#define GLUE(a,b) a##b
STRINGAFY1(GLUE(PART1,PART2*))
//yields
"PART1PART2*"
I am using MSVC++ from VS.net 2005 sp1
Edit:
it is currently my belief that the preprocessor works like this when expanding macros:
Step 1:
– take the body
– remove any whitespace around ## operators
– parse the string, in the case that an identifier is found that matches the name of a parameter:
-if it is next to a ## operator, replace the identifier with the literal value of the parameter (i.e. the string passed in)
-if it is NOT next to a ## operator, run this whole explanation process on the value of the parameter first, then replace the identifier with that result.
(ignoring the stringafy single ‘#’ case atm)
-remove all ## operators
Step 2:
– take that resultant string and parse it for any macros
now, from that I believe that all 3 cases should produce the exact same resultant string:
PART1PART2*
and hence after step 2, should result in
works*
but at very least should result in the same thing.
cases 1 and 2 have no defined behavior since your are tempting to paste a
*into one preprocessor token. According to the association rules of your preprocessor this either tries to glue together the tokensPART1PART2(or justPART2) and*. In your case this probably fails silently, which is one of the possible outcomes when things are undefined. The tokenPART1PART2followed by*will then not be considered for macro expansion again. Stringfication then produces the result you see.My gcc behaves differently on your examples:
So to summarize your case 1 has two problems.
in a valid preprocessor token.
##operatorIn case 3, your compiler is giving the wrong result. It should
STRINGAFY1GLUEGLUEresults inPART1PART2*works*STRINGAFY1