1

Let's say I have a macro in an inclusion file:

// a.h
#define VALUE SUBSTITUTE

And another file that includes it:

// b.h
#define SUBSTITUTE 3
#include "a.h"

Is it the case that VALUE is now defined to SUBSTITUTE and will be macro expanded in two passes to 3, or is it the case that VALUE has been set to the macro expanded value of SUBSTITUTE (i.e. 3)?

I ask this question in the interest of trying to understand the Boost preprocessor library and how its BOOST_PP_SLOT defines work (edit: and I mean the underlying workings). Therefore, while I am asking the above question, I'd also be interested if anyone could explain that.

(and I guess I'd also like to know where the heck to find the 'painted blue' rules are written...)

user
  • 4,920
  • 3
  • 25
  • 38

1 Answers1

1

VALUE is defined as SUBSTITUTE. The definition of VALUE is not aware at any point that SUBSTITUTE has also been defined. After VALUE is replaced, whatever it was replaced by will be scanned again, and potentially more replacements applied then. All defines exist in their own conceptual space, completely unaware of each other; they only interact with one another at the site of expansion in the main program text (defines are directives, and thus not part of the program proper).

The rules for the preprocessor are specified alongside the rules for C proper in the language standard. The standard documents themselves cost money, but you can usually download the "final draft" for free; the latest (C11) can be found here: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf

For at-home use the draft is pretty much equivalent to the real thing. Most people who quote the standard are actually looking at copies of the draft. (Certainly it's closer to the actual standard than any real-world C compiler is...)

There's a more accessible description of the macro rules in the GCC manual: http://gcc.gnu.org/onlinedocs/cpp/Self_002dReferential-Macros.html


Additionally... I couldn't tell you much about the Boost preprocessor library, not having used it, but there's a beautiful pair of libraries by the same authors called Order and Chaos that are very "clean" (as macro code goes) and easy to understand. They're more academic in tone and intended to be pure rather than portable; which might make them easier reading.

(Since I don't know Boost PP I don't know how relevant this is to your question but) there's also a good introductory example of the kids of techniques these libraries use for advanced metaprogramming constructs in this answer: Is the C99 preprocessor Turing complete?

Community
  • 1
  • 1
Alex Celeste
  • 12,824
  • 10
  • 46
  • 89
  • Makes sense. I was under the impression initially that `#include`s somehow had special consideration. I've been an avid user of template metaprogramming for a while now and have only recently gotten interested in the PP. I actually read the post you linked to earlier, and straight-copy-pasted the sample, only to find that it wouldn't work under my version of GCC nor MSVC (which is reportedly broken with regards to `__VA_ARGS__` expansion anyway, but even with repeated applications of the `#define EXPAND(...) __VA_ARGS__` workaround it failed to work). I guess that's for another question. – user Jun 14 '13 at 00:18