75

What I'm trying to figure out is if something such as this (written in C):

#define FOO 15
#define BAR 23
#define MEH (FOO / BAR)

is allowed? I would want the preprocessor to replace every instance of

MEH

with

(15 / 23)

but I'm not so sure that will work. Certainly if the preprocessor only goes through the code once then I don't think it'd work out the way I'd like.

I found several similar examples but all were really too complicated for me to understand. If someone could help me out with this simple one I'd be eternally grateful!

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
llakais
  • 1,577
  • 1
  • 12
  • 18
  • 4
    Before reading your question, I thought you were asking whether a macro definition can define another macro, such as `#define FOO(x) #define BAR x`. The answer to that question (which you didn't actually ask) is no; a macro *definition* cannot include further preprocessor directives. I'm going to edit your title to make it clearer what you're asking. – Keith Thompson Nov 01 '11 at 21:01
  • Google X-Macros, enjoy. – Jake Nov 01 '11 at 21:47

6 Answers6

67

Short answer yes. You can nest defines and macros like that - as many levels as you want as long as it isn't recursive.

Mysticial
  • 464,885
  • 45
  • 335
  • 332
  • 11
    Is order important? Can `MEH` be #defined first? – David Heffernan Nov 01 '11 at 21:04
  • 1
    I can't quote the standard, but I think it does not matter. I've been doing both forward and backward nested macro definitions for a long time and it works in VC++, GCC, ICC, etc... – Mysticial Nov 01 '11 at 21:07
  • 18
    @DavidHeffernan: The order is not important, all that matters is to have `MEH`, `FOO` and `BAR` all defined when `MEH` appears. The preprocessor first replaces `MEH` with `(FOO / BAR)`, then start again, replacing first `FOO` with `15` then `BAR` with `23` – DirtY iCE Nov 01 '11 at 21:09
  • 1
    (Confirming order does not matter) Note that you can even define `MEH` first (which is based on `FOO` and `BAR`), then `FOO` and `BAR` afterwards, and it still works just fine. This initially seems like it shouldn't work, but again, it works just fine. Therefore, the preprocessor must either store every define in a hash table as it goes, updating items as it finds new definitions, or it must do multiple passes. Regardless of *how* it does it, it does indeed work, regardless of the order of the defines. – Gabriel Staples Mar 04 '19 at 21:40
40

The answer is "yes", and two other people have correctly said so.

As for why the answer is yes, the gory details are in the C standard, section 6.10.3.4, "Rescanning and further replacement". The OP might not benefit from this, but others might be interested.

6.10.3.4 Rescanning and further replacement

After all parameters in the replacement list have been substituted and # and ## processing has taken place, all placemarker preprocessing tokens are removed. Then, the resulting preprocessing token sequence is rescanned, along with all subsequent preprocessing tokens of the source file, for more macro names to replace.

If the name of the macro being replaced is found during this scan of the replacement list (not including the rest of the source file's preprocessing tokens), it is not replaced. Furthermore, if any nested replacements encounter the name of the macro being replaced, it is not replaced. These nonreplaced macro name preprocessing tokens are no longer available for further replacement even if they are later (re)examined in contexts in which that macro name preprocessing token would otherwise have been replaced.

The resulting completely macro-replaced preprocessing token sequence is not processed as a preprocessing directive even if it resembles one, but all pragma unary operator expressions within it are then processed as specified in 6.10.9 below.

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
21

Yes, it's going to work.


But for your personal information, here are some simplified rules about macros that might help you (it's out of scope, but will probably help you in the future). I'll try to keep it as simple as possible.

  • The defines are "defined" in the order they are included/read. That means that you cannot use a define that wasn't defined previously.

  • Usefull pre-processor keyword: #define, #undef, #else, #elif, #ifdef, #ifndef, #if

  • You can use any other previously #define in your macro. They will be expanded. (like in your question)

  • Function macro definitions accept two special operators (# and ##)

operator # stringize the argument:

#define str(x) #x
str(test); // would translate to "test"

operator ## concatenates two arguments

#define concat(a,b) a ## b
concat(hello, world); // would translate to "helloworld"

There are some predefined macros (from the language) as well that you can use:

__LINE__, __FILE__, __cplusplus, etc

See your compiler section on that to have an extensive list since it's not "cross platform"

  • Pay attention to the macro expansion

You'll see that people uses a log of round brackets "()" when defining macros. The reason is that when you call a macro, it's expanded "as is"

#define mult(a, b) a * b
mult(1+2, 3+4); // will be expanded like: 1 + 2 * 3 + 4 = 11 instead of 21.
mult_fix(a, b) ((a) * (b))
Sauleil
  • 2,573
  • 1
  • 24
  • 27
4

Yes, and there is one more advantage of this feature. You can leave some macro undefined and set its value as a name of another macro in the compilation command.

#define STR "string"
void main() { printf("value=%s\n", VALUE); }

In the command line you can say that the macro "VALUE" takes value from another macro "STR":

$ gcc -o test_macro -DVALUE=STR main.c
$ ./test_macro

Output:

value=string

This approach works as well for MSC compiler on Windows. I find it very flexible.

Alexander Samoylov
  • 2,358
  • 2
  • 25
  • 28
2

I'd like to add a gotcha that tripped me up.

Function-style macros cannot do this.

Example that doesn't compile when used:

#define FOO 1
#define FSMACRO(x) FOO + x
Stefan Monov
  • 11,332
  • 10
  • 63
  • 120
0

Yes, that is supported. And used quite a lot!

One important thing to note though is to make sure you paranthesize the expression otherwise you might run into nasty issues!

#define MEH FOO/BAR

// vs

#define MEH (FOO / BAR)

// the first could be expanded in an expression like 5 * MEH to mean something 
//   completely different than the second
Mike Dinescu
  • 54,171
  • 16
  • 118
  • 151
  • Miky, a small correction: parenthesis should be definitely used in macros, but are not necessary in this case: x * (FOO / BAR) == (x * FOO) / BAR == x * FOO / BAR – Zaur Nasibov Nov 01 '11 at 21:16
  • The second definition might have issues too, for example when `FOO` is `2+2` – anatolyg Nov 01 '11 at 21:18
  • 1
    @BasicWolf Integer division makes it problematic: `5 * (10/3)` is 15, while `5 * 10/3` is 16 – anatolyg Nov 01 '11 at 21:22
  • @anatolyg: Yes, but typically macros that expand to expressions already parenthesize the expression specifically to avoid suprises when the macro is used. –  Nov 01 '11 at 21:22
  • @BasicWolf: Your reasoning is incorrect. Arithmetic equalities like the one you cited are true for fields, but neither integers nor floating point numbers form a field. – R.. GitHub STOP HELPING ICE Nov 01 '11 at 21:29
  • Thank you guys, your comments would definitely save me debugging time in future :) – Zaur Nasibov Nov 01 '11 at 21:35
  • 2
    I've just uploaded a particularly egregious example of C preprocessor abuse [here](https://raw.github.com/Keith-S-Thompson/42/master/42.c). See the README file for [the repository](https://github.com/Keith-S-Thompson/42). – Keith Thompson Nov 01 '11 at 22:05