Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does the math library only need to be linked when used outside of main? [duplicate]

Tags:

c

gcc

ld

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.

like image 644
ratorx Avatar asked Jun 01 '18 15:06

ratorx


2 Answers

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.

like image 161
Bathsheba Avatar answered Nov 15 '22 02:11

Bathsheba


Since the argument to sqrt is known at compile time, and its behaviour is standardised, sqrt(4.0) can be calculated at compile time.

like image 26
Maxim Egorushkin Avatar answered Nov 15 '22 03:11

Maxim Egorushkin