Reputation: 27583
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?
Example:
#define EXTERNAL_CLOCK_FREQUENCY 32768
#define TIMER_1_S EXTERNAL_CLOCK_FREQUENCY
#define TIMER_100_MS TIMERB_1_S / 10
Will the operation 32768 / 10 occur at runtime every time I use the TIMER_100_MS macro?
I would like to avoid the following:
#define EXTERNAL_CLOCK_FREQUENCY 32768
#define TIMER_1_S EXTERNAL_CLOCK_FREQUENCY
#define TIMER_100_MS 3276
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.
Upvotes: 37
Views: 23508
Reputation: 506925
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
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.
Edit: As a comment notes, if the macro is substituted into an expression like 3 * TIMER_100_MS
, then this would evaluate (3 * 32768) / 10
. Therefore, the simple and direct answer is "No, it would not occur at runtime every time, because the division may not occur at all because of precedence and associativity rules". My answer above assumes that the macro is always substituted such that the division actually happens.
Upvotes: 30
Reputation: 93
It`s incorrect, compilers can not manipulate floating point numbers at compile time. If you are satisfied with 3276 value at compile time then you are good to go, but there is no way compiler going to evaluate this at compile time with floating point precision. Floating points are too tricky for compilers to optimize, because optimizing a floating point number can lead to unexpected results in mathematical expressions, so a decent compiler (any gcc version, any clang version, any msvc version, any icc version) wont simplify it to 3276.8 , end of story.
And the other part of your question, you asked will it is going to be evaluated for each macro expansion. Again if you are fine with 3276 value then the answer is no, it depends from compiler, optimization level and the background, it can be placed in constant table or it can be inlined in code. Ever way you wont compute the same expression in runtime for each macro expansion. Again, if you want floating point precision to get 3276.8, than that expression will be evaluated for each macro expansion in run time.
Take a look here for more compilation and optimization aspects: http://www.agner.org/optimize/#manuals
Upvotes: 0
Reputation: 202505
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 /
.
Upvotes: 8
Reputation: 27583
From the WG14/N1124 Committee Draft — May 6, 2005 ISO/IEC 9899:TC2:
6.6 Constant expressions
Syntax
constant-expression:
conditional-expressionDescription
A constant expression can be evaluated during translation rather than runtime, and accordingly may be used in any place that a constant may be.
Constraints
Constant expressions shall not contain assignment, increment, decrement, function-call, or comma operators, except when they are contained within a subexpression that is not evaluated.96)
Each constant expression shall evaluate to a constant that is in the range of epresentable values for its type.
Upvotes: 14
Reputation: 1198
At compile time. This is a language standard (and always have been) and independent on the compiler.
Edit
A commenter asked for a reference - quoting from "The C programming language" 2nd edition Appendix A12.3 (p. 229):
A control line of the form
#define identifier token-sequence
causes the preprocessor to replace subsequent instances of the identifier with the given sequence of tokens; leading and trailing whitespace around the roken sequence is discaded
End of edit
Upvotes: -4
Reputation: 68033
The compiler should optimize that expression out. I don't think it's requited to by the standard, but I've never seen a compiler that would NOT perform that task.
However, you should NOT write:
#define TIMER_100_MS TIMERB_1_S / 10
... because that's a bug waiting to happen. You should always parenthesize #defines involving expressions.
#define TIMER_100_MS (TIMERB_1_S / 10)
Consider :
i = 10 * TIMER_100_MS;
The first case would give 32768 ((10 * TIMERB_1_S) / 10) , the second 32760 (10 * (TIMERB_1_S / 10)). Not a critical difference here, but you MUST be aware of it!
Upvotes: 11
Reputation: 57036
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.
Upvotes: 38
Reputation: 10955
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:
#include <stdlib.h>
#include <stdio.h>
#define EXTERNAL_CLOCK_FREQUENCY 32768
#define TIMER_1_S EXTERNAL_CLOCK_FREQUENCY
#define TIMER_100_MS TIMER_1_S / 10
int main(int argc, char **argv)
{
printf("%d\n", TIMER_100_MS);
return(0);
}
gcc -S test.c
cat test.s
...
popl %ebx
movl $3276, 4(%esp)
leal LC0-"L00000000001$pb"(%ebx), %eax
movl %eax, (%esp)
call L_printf$stub
...
Upvotes: 16
Reputation: 405745
Will the operation 32768 / 10 occur at runtime every time I use the TIMERB_100_MS macro?
Every place in your code where you use TIMERB_100_MS
, it will be replaced with 32768 / 10
by the preprocessor.
Whether that expression gets further optimized (it evaluates to a constant) is up to your compiler.
Upvotes: 9