1

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?

enter image description here

#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

12
  • I guess #pragma is from VC Commented Jan 28, 2019 at 11:54
  • @Mayur #pragma is standard C for something that isn't standard C :) The stuff that comes after #pragma will be compiler-specific, and compilers who don't recognize it are required to ignore it. Anyway, this isn't what the question is about, but rather pre-processor expansion of macro parameters. Commented Jan 28, 2019 at 12:11
  • 1
    @StoryTeller Better dupe? stackoverflow.com/questions/16989730/… Commented Jan 28, 2019 at 12:28
  • 1
    @StoryTeller Ok fair enough, maybe this question is specific enough. I'll re-open. And also swap the canonical dupe in the wiki, because I agree that the first one I used didn't have very good answers. Commented Jan 28, 2019 at 12:31
  • 1
    @Hasan alattar Regarding the difference between #pragma and _Pragma, the former is a pre-processor directive, the latter is an operator to be used inside other pre-procesor directives. Both are standard C and used to portably indicate that something following is not standard C. Commented Jan 28, 2019 at 12:42

1 Answer 1

2

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.

Sign up to request clarification or add additional context in comments.

5 Comments

@user694733 - Not really. The stringification of "x" is "\"x\"", and that's standard. The OP is just re-wrapping redundantly. But that is beside the point for this specific question, and for the OP to figure out as they continue on their refinement of the utility.
i could not make the examples you showed to work. although i understand from your answer that i was wrapping randomly. i removed '#' from TODO macro and everything works!
@Hasanalattar - I don't know what you did and how it did not work, obviously I'm not psychic. But if you could not get the whole thing expanded still, the solution could be to just turn EMPTY EMPTY()() into EMPTY EMPTY EMPTY EMPTY()()()()
@user694733 - The argument to _Pragma must be a literal with the contents one would give #pragma. So if the we want the equivalent of #pragma message ... we need to produce _Pragma("message ..."). The #x in DO_PRAGMA is thus correct given TODO.
@StoryTeller i did not change anything. once it didnt work i pasted my code from the original question.. maybe because you assume im using microsoft VC while im using Atmel studio which has the compiler: arm-none-eabi-g++.exe.. image anyway thank you your answer make sense but i cant understand the DEFER and EMPTY part or make it work..

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.