im trying to understand preprocessor.
why one of the bellow preprocessor macro doesn't work while the other does
what is the difference between #pragma and _Pragma
why do we wrap STRINGZ with ASTRINGZ?
#define STRINGZ(x) #x
#define ASTRINGZ(x) STRINGZ(x)
#define DO_PRAGMA(x) _Pragma (#x)
#define TODO(x) DO_PRAGMA(message ("TODO - " #x))
#define msg(s) TODO( s " - @ - " ASTRINGZ(__FILE__))
msg ("This doesnt work")
#pragma message "but this does: " ASTRINGZ(__FILE__)
sources:
https://gcc.gnu.org/onlinedocs/gcc/Diagnostic-Pragmas.html
http://forums.codeguru.com/showthread.php?215151-LINE-MACRO-to-string-literal&p=613574#post613574
why one of the bellow preprocessor macro doesn't work while the other does
While the preprocessor will expand most further macros that result out of a current expansion, it will only do a single expansion step. So ASTRINGZ(__FILE__)
is not going to be expanded all the way before being passed to the stringification of TODO
.
You have several options to deal with this, the easiest is to rely on the fact __FILE__
is already a string literal.
#define msg(s) TODO( s " - @ - " __FILE__)
But if you wish to experiment with macro expansion, you can try a deferring technique. This will delay the moment TODO
is actually expanded itself, and give the arguments time to be expanded themselves.
#define EMPTY()
#define DEFER(m) m EMPTY EMPTY()()
#define msg(s) DEFER(TODO)( s " - @ - " ASTRINGZ(__FILE__))
The above makes the ( s " - @ - " ASTRINGZ(__FILE__))
not be arguments to a macro, so ASTRINGZ
will be expanded. DEFER(TODO)
is a macro however, so it will be expanded to TODO EMPTY EMPTY()()
. It will take two more expansion cycles (each EMPTY()
for TODO (...)
to be handed back to the preprocessor. At which point everything should be properly expanded.
what is the difference between #pragma and _Pragma
_Pragma
is another standard way to provide compiler specific pragma directive. The difference is that _Pragma
can be the result of macro expansion, while #pragma
being a directive may not.
why do we wrap STRINGZ with ASTRINGZ?
It's another deferral technique. In case the argument to ASTRINGZ
is itself the result of some non-trivial preprocssor expansion.