If I write a #define that performs an operation using other preprocessor constants, is the final value computed each time the macro appears at runtime? Does this depend on optimizations in the compiler, or is it covered under a standard?

Summary

A compiler is required to be able to evaluate constant integral expressions because they are necessary for calculating things like array sizes at compile time. However, the standard only says they "can" -- not "must" -- do so. Therefore, only a brain-dead compiler would not evaluate a constant integral expressions at compile time, but a simple check of the assembly output for an unconventional compiler would verify each case.

9 Answers
9

Macros are simply textual substitution, so in your example writing TIMER_100_MS in a program is a fancy way of writing 32768 / 10.

Therefore, the question is when the compiler would evaluate 32768 / 10, which is a constant integral expression. I don't think the standard requires any particular behavior here (since run-time and compile-time evaluation is indistinguishable in effect), but any halfway decent compiler will evaluate it at compile time.

This is the key point. The preprocessor manipulates text, then the compiler gets it and knows nothing about how much preprocessing has gone before...
–
dmckeeJan 12 '09 at 18:16

Even if the preprocessor would do so, it can't do so as long it isn't defined this way: #define TIMER_100_MS (TIMERB_1_S / 10) Since you don't paranthese the expression, It would be wring to evaluate it to 3277 where you might have written 1 / TIMER_100_MS (Where the result anyway wouldn't be what is wanted I guess) But if the preprocessor had evaluated the statement here allready the it would even break the operator priority order.
–
ZaibisFeb 12 at 12:18

Most answers in here focused on the effect of the macro substitution. But i think he wanted to know whether

32768 / 10

is evaluated at compile time. First of all, that is an arithmetic constant expression, and in addition a integral constant expression (because it has only got literals of integer type). The implementation is free to calculate it at runtime, but it must also be able to calculate it at compile time, because

it must give a diagnostic message if a constant expression is not representable in the type that its expression has

such expressions are allowed in contexts that require the value at translation time, for example if used as the size of an array dimension.

If the compiler can principally calculate the result already at compile time, it should use that value, and not recalculate it at runtime i think. But maybe there is some reason still to do that. I wouldn't know.

Edit: I'm sorry i've answered the question as if it were about C++. Noticed today you asked about C. Overflowing in an expression is deemed as undefined behavior in C, regardless of whether it happens in a constant expression or not. The second point is also true in C, of course.

I'm not aware of any standard that guarantees it will be optimized out. The preprocessor will substitute 32768/10 for TIMER_100_MS, which you can see by running gcc -c. To see whether the compiler is optimizing further, run gcc -S and check out the assembler. With gcc 4.1, even without any optimization flags, this gets reduced to the constant during compilation:

Folks, this transformation is called "constant folding" and even most student compilers do it. As long as you have a compiler built by somebody not you or your college roommate and you're compiling a statically typed language, you can count on it even without optimization turned on. It's a different matter if you're dealing with some wacky dynamic language that is allowed to change the meaning of /.

I'm totally confused now. You post a reply which contradicts this (says they "can" be evaluated at translation time, not they "must" be.
–
RoddyJan 12 '09 at 19:36

@David: the macro will be EXPANDED at compile time (how else could it be), but there is no guarantee that the expression "TIMERB_1_S / 10" (ie the division) is not evaluated at runtime.
–
RoddyJan 12 '09 at 19:54

I don't see how that is relevant. If that answers the question that was being asked, the question needs to be rewritten.
–
BCSJan 12 '09 at 22:49