sqrt from math.h causes linker error "undefined reference to sqrt" only when the argument is not a constant
I created a small program, as follows:
#include <math.h>
#include <stdio.h>
#include <unistd.h>
int main(int argc, char *argv[]) {
int i;
double tmp;
double xx;
for(i = 1; i <= 30; i++) {
xx = (double) i + 0.01;
tmp = sqrt(xx);
printf("the square root of %0.4f is %0.4f\n", xx,tmp);
sleep(1);
xx = 0;
}
return 0;
}
When I try to compile this with the following command, I get a compiler error.
gcc -Wall calc.c -o calc
returns:
/tmp/ccavWTUB.o: In function `main':
calc.c:(.text+0x4f): undefined reference to `sqrt'
collect2: ld returned 1 exit status
If I replace the variable in the call to sqrt(xx) with a constant like sqrt(10.2), it compiles just fine. Or, if I explicitly link like the following:
gcc -Wall -lm calc.c -o calc
It also works just fine. Can anyone tell me what's causing this? I've been a C programmer for a long time (and I've written similar small programs using math.h) and I have never seen anything like this.
My version of gcc follows:
$ gcc --version
gcc (Ubuntu 4.3.3-5ubuntu4) 4.3.3
Copyright (C) 2008 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
$
If you look at the output of the compiler in the case where you used sqrt(10.2)
, I'll bet you see that a call to sqrt()
isn't actually made.
This happens because GCC recognizes several functions that it can treat specially. This gives it the ability to do certain optimizations, in this case Constant folding. Such special functions are called Built-ins.
In the case where it must link to the math library (because you're calling it with a variable), you need to link it explicitly. Some operating systems/compilers do it for you, which is why you might not have noticed in the past.