I tend to use math functions of constant expressions for convinience and coherence (i.e log(x)/log(2)
instead of log(x)/0.3...
). Since these functions aren't actually a part of the language itself, neither are they defined in math.h
(only declared), will the constant ones get precalculated at compile time, or will they be wastefully calculated at runtime?

- 4,321
- 6
- 26
- 19
-
I would expect they would get precalculated but it would help if you said what compiler you were using so people could actually check. – Hazior Jan 12 '10 at 14:04
-
1log(x), of course, is not a constant expression at compile time, unless x has previously been declared to be a constant and given a value. It's probably not too hard to write code which no compiler will evaluate even if it is easy for a human to do so. – High Performance Mark Jan 12 '10 at 14:09
-
It's been a long time since I ran into this, but there have been implementations that allowed some details of floating-point calculations to be specified at runtime. In that case, nothing depending on that could be calculated at compile time. – David Thornley Jan 12 '10 at 15:05
6 Answers
It depends on the compiler and the optimization flags. As @AndrewyT points out, GCC has the ability to specify which functions are constant and pure via attributes, and in this case the answer is positive, it will inline the result, as you can easily check:
$ cat constant_call_opt.c
#include <math.h>
float foo() {
return log(2);
}
$ gcc -c constant_call_opt.c -S
$ cat constant_call_opt.s
.file "constant_call_opt.c"
.text
.globl foo
.type foo, @function
foo:
pushl %ebp
movl %esp, %ebp
subl $4, %esp
movl $0x3f317218, %eax
movl %eax, -4(%ebp)
flds -4(%ebp)
leave
ret
.size foo, .-foo
.ident "GCC: (Ubuntu 4.3.3-5ubuntu4) 4.3.3"
.section .note.GNU-stack,"",@progbits
no function call there, just loads a constant (0x3f317218 == 0.69314718246459961 == log(2)
)
Althought I have not any other compiler at hand to try now, I think you could expect the same behaviour in all the major C compilers out there, as it's a trivial optimization.

- 74,053
- 25
- 135
- 175
-
1If you can't instantly decode 32-bit IEEE floating point encodings like 0x3f317218 in your head, try compiling `log(1.0)` which results in the nice easy constant `$0x0` in that `movl $0x0 , %eax` line. – Mark Lakata May 17 '16 at 23:58
Some compilers will evaluate them at compile time, but this behavior is not guaranteed (and doing so may also cause problems). You'll need to check your compiler and see what it does.
Note that on many systems, log(2)
is available from the macro M_LN2
in <math.h>
.

- 103,815
- 19
- 183
- 269
-
2If the compiler knows that log has no side effects and always returns the same value (eg, is a 'pure' function), it could evaluate them at compile time. Since the user has the option of replacing the functions from the math library and could choose to replace log with a function that does not return the same value for log(2) each time it is invoked or that has side effects, the compiler cannot evaluate it at compile time. – William Pursell Jan 12 '10 at 15:21
-
1I'm able to get this behavior on two different compilers (gcc, icc) in strict mode when the result is exact (eg `pow(2.0, 2.0)`) and the call is therefore (in theory) side-effect free under the assumption that the user hasn't substituted their own routine. While I agree with your analysis that the compilers probably shouldn't be doing this, they seem to be perfectly willing to do it anyway =/. It wouldn't surprise me if some compilers do it even when the flags are affected, as compiler writers generally have a pretty dim view of floating point state. – Stephen Canon Jan 12 '10 at 16:17
-
2It's allowed because programs that (try to) replace any of the standard functions are no longer conforming C programs. – caf Jan 13 '10 at 00:55
They'll usually get calculated at runtime (see other answers for how to inline them), though I wouldn't necessarily use the word "wastefully" unless there were a lot of them and/or the code was executed lots of times.
Rather than just put in the constant value, create a #define
or const
variable that expresses what the value means (PI
, LOG_2
, etc.) and use that instead.
For example:
#define LOG_2 0.30102999566
This doesn't do any calculation and you can specify the value to what ever precision you desire or can manage given your environment (32 bit v 64 bit).

- 134,786
- 31
- 255
- 325
-
3Careful! If you do `#define LOG_2 (log(2))`, that calls `log()` any time you use `LOG_2`. A `const` global variable is a *much* better idea. – Mike DeSimone Jan 12 '10 at 14:56
-
1@Mike - I wasn't suggesting you do that but do `#define LOG_2 0.30102999` (or to how ever many dp you want) – ChrisF Jan 12 '10 at 15:00
-
1you're wrong asserting that categorically, at least with GCC they're computed at compile time. – fortran Jan 12 '10 at 16:38
-
Well you could specify the values to arbitrary number of decimal places, but the actual values stored would be truncated to what would fit within the desired floating point value (32 or 64 bit). So you're best off using as many decimal places as can be fit into the most precise number format that you work with. A double/64bit floating point value would be something around 11 decimal places. – Dominik Grabiec Jan 12 '10 at 17:01
It depends. If the compiler can do the math exactly as it would be done at runtime, and if link time optimizations are performed, and if the library is kept in some sort of intermediate form, then yes it could be done.
Most compilers don't do all of that.

- 19,673
- 4
- 43
- 72
In case of library functions, some compiler might implement these functions as intrinsics, meaning that the compiler knows enough about the functions to replace the call with a constant at compile time. Whether it will do this depends on the compiler. In practice, I often notice that some compilers are reluctant to pre-calculate floating-point expressions at compile time, even if they don't involve any function calls.
In general case, normally they won't and can't get calculated at compile time, assuming the compiler simply doesn't know enough about these functions to be able to calculate them at compile time. Maybe they have some prominent run-time side-effects?
Some compilers might have non-standard compiler-dependent extensions that allow user to provide the additional information about the functions to the compiler, so that the compiler can optimize function calls better and even figure out whether a given call can be replaced with a compile-time pre-calculation. For example, GCC compiler supports such function attributes (GCC-specific extension) as const
and pure
. If the arguments are known at compile time, a call to function with the const
attribute can be theoretically replaced with compile-time pre-calculation. Although I can't say whether GCC can actually do this.
In C++ (even though your question is tagged C) language a planned new feature is a constexpr
declaration specifier that serves a similar purpose and supposed to have the effect you describe.

- 312,472
- 42
- 525
- 765
This happens at runtime since the code for the function only becomes available during the linking step (which happens after the compile step).
To optimize the step, use a global variable which you initialize before you use it.

- 321,842
- 108
- 597
- 820
-
1Except that if it's a standard function declared in an included standard header, the implementation does know about it. – David Thornley Jan 12 '10 at 16:48
-
You're wrong: It knows that the function *exists* but that doesn't mean the functions declared in standard header files get any special treatment. From the compiler's point of view, they are just like any other function from any other header file. Also, the compiler can't link so there is no way for it to load and execute any function, standard or not. – Aaron Digulla Jan 13 '10 at 07:59