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 tokens PART1PART2
(or just PART2
) and *
. In your case this probably fails silently, which is one of the possible outcomes when things are undefined. The token PART1PART2
followed by *
will then not be considered for macro expansion again. Stringfication then produces the result you see.
My gcc behaves differently on your examples:
/usr/bin/gcc -O0 -g -std=c89 -pedantic -E test-prepro.c
test-prepro.c:16:1: error: pasting "PART1PART2" and "*" does not give a valid preprocessing token
"works*"
So to summarize your case 1 has two problems.
##
operatorIn case 3, your compiler is giving the wrong result. It should
STRINGAFY1
GLUE
GLUE
results in PART1PART2*
works*
STRINGAFY1
It's doing exactly what you are telling it to do. The first and second take the symbol names passed in and paste them together into a new symbol. The third takes 2 symbols and pastes them, then you are placing the * in the string yourself (which will eventually evaluate into something else.)
What exactly is the question with the results? What did you expect to get? It all seems to be working as I would expect it to.
Then of course is the question of why are you playing with the dark arts of symbol munging like this anyways? :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With