Using gcc test.c
, the first code sample compiles, while the second does not. Why?
They both work with explicit linking of the math library (i.e. gcc test.c -lm
.
First Sample:
#include <stdio.h>
#include <math.h>
int main () {
printf("%lf\n", sqrt(4.0) );
return 0;
}
Second Sample:
#include <math.h>
#include <stdio.h>
double sqrt2(double a) { return sqrt(a); }
int main() {
printf("%lf\n", sqrt(4.0));
printf("%lf\n", sqrt2(4.0));
return 0;
}
Linker error with second sample:
/tmp/ccuYdso7.o: In function `sqrt2':
test.c:(.text+0x13): undefined reference to `sqrt'
collect2: error: ld returned 1 exit status
gcc -v:
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-pc-linux-gnu/8.1.0/lto-wrapper
Target: x86_64-pc-linux-gnu
Configured with: /build/gcc/src/gcc/configure --prefix=/usr --libdir=/usr/lib --libexecdir=/usr/lib --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=https://bugs.archlinux.org/ --enable-languages=c,c++,ada,fortran,go,lto,objc,obj-c++ --enable-shared --enable-threads=posix --enable-libmpx --with-system-zlib --with-isl --enable-__cxa_atexit --disable-libunwind-exceptions --enable-clocale=gnu --disable-libstdcxx-pch --disable-libssp --enable-gnu-unique-object --enable-linker-build-id --enable-lto --enable-plugin --enable-install-libiberty --with-linker-hash-style=gnu --enable-gnu-indirect-function --enable-mul
Thread model: posix
gcc version 8.1.0 (GCC)
There is no linker error for uses of sqrt
in the main function. Is there any particular reason that this is the case?
I also checked with clang, but neither compiled (linker errors) without the -lm
.
gcc is a particularly clever compiler.
It will optimise out sqrt(4.0)
as a compile time evaluable constant expression. It can do that since the definition of sqrt
is defined by the standard and its return value is solely a function of its input. (Note futher that under IEEE754, sqrt
must return the closest double
to the final result. This further supports the optimisation hypothesis.)
In the second case, the presence of function (which could be used by other translation units) defeats this optimisation.
Since the argument to sqrt
is known at compile time, and its behaviour is standardised, sqrt(4.0)
can be calculated at compile time.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With