Given
#define cat(x,y) x##y
The call cat(a,1)
returns a1
, but cat(cat(1,2),3)
is undefined.
However if I also define #define xcat(x,y) cat(x,y)
, then the result of xcat(xcat(1,2),3)
is now 123
. Can anybody please explain in detail why this is so?
I tested this using both GCC and Clang.
GCC gives the error:
test.c:6:1: error: pasting ")" and "3" does not give a valid preprocessing token
Clang gives the error:
test.c:6:11: error: pasting formed ')3', an invalid preprocessing token
int b = cat(cat(1,2),3);
What appears to be happening is that the compiler wraps the result of cat(1,2)
in parentheses as soon as it is expanded; so when you call cat(1,2)
in your code, it really gives you (12)
. Then, calling cat((12),3)
again leads to ((12)3)
, which is not a valid token, and this results in a compile error.
The common opinion is "when using the token-pasting operator (##), you should use two levels of indirection" (i.e., use your xcat
workaround). See Why do I need double layer of indirection for macros? and What should be done with macros that need to paste two tokens together?.
In xcat(x,y), the x and y are not adjacent to the ## operator, and so they undergo macro expansion before being substituted.
So x is identified as xcat(1,2) and y is identified as 3. But prior to substitution, x is macro-expanded to cat(1,2), which turns into 1##2 which turns into 12. So ultimately, xcat(xcat(1,2),3) will expand to cat(12,3), which will turn out 123.
This Works --> cat(xcat(1,2),3) --> cat(cat(1,2),3) --> cat(12,3)
The behavior is well-defined because all of the token pastings result in valid preprocessor tokens i.e any expanded xpression should be a valid token at any stage.
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