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

StoryTeller - Unslander Monica
  • 165,132
  • 21
  • 377
  • 458
Hasan alattar
  • 347
  • 3
  • 19
  • I guess `#pragma ` is from VC – Mayur Jan 28 '19 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. – Lundin Jan 28 '19 at 12:11
  • @Lundin Thanks for information – Mayur Jan 28 '19 at 12:13
  • @Lundin - Hardly a duplicate of that question. If you could not find anything better for a dupe target, it should not have been closed. – StoryTeller - Unslander Monica Jan 28 '19 at 12:15
  • @StoryTeller It's the dupe we use for "how do stringify macros work". It might not be ideal, but this has been asked many times before. The only part not addressed is the `_Pragma` non-standard syntax. – Lundin Jan 28 '19 at 12:18
  • @Lundin - Then surely you can link to the appropriate meta discussion. If not, I can only take "we" to mean "me" (as in you). And I'm afraid I do not agree, and am inclined to re-open. – StoryTeller - Unslander Monica Jan 28 '19 at 12:19
  • @StoryTeller It's the one listed under the C tag wiki FAQ, which can be maintained by anyone. I'm searching to see if I can find a better one. – Lundin Jan 28 '19 at 12:21
  • 1
    @StoryTeller Better dupe? https://stackoverflow.com/questions/16989730/stringification-how-does-it-work – Lundin Jan 28 '19 at 12:28
  • @Lundin - As a canonical for the sort `STR` macro, definitely. But the issue here is that the `STR` macro is not expanded. It needs a deferral. I still think this hasn't been asked before. But it's not hill to die on. – StoryTeller - Unslander Monica Jan 28 '19 at 12:29
  • 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. – Lundin Jan 28 '19 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. – Lundin Jan 28 '19 at 12:42
  • @Lundin thanks, sorry for the repeated part of the question. i think i need to research more about deferral to expand .. – Hasan alattar Jan 28 '19 at 13:14

1 Answers1

1

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.

StoryTeller - Unslander Monica
  • 165,132
  • 21
  • 377
  • 458
  • 2
    @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. – StoryTeller - Unslander Monica Jan 28 '19 at 12:14
  • 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! – Hasan alattar Jan 28 '19 at 12:41
  • @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()()()()` – StoryTeller - Unslander Monica Jan 28 '19 at 12:44
  • @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 - Unslander Monica Jan 28 '19 at 12:52
  • @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](https://snag.gy/H3Cu1l.jpg) anyway thank you your answer make sense but i cant understand the DEFER and EMPTY part or make it work.. – Hasan alattar Jan 28 '19 at 13:01