So, I know that in C you need to link the code to the math library, libm, to be able to use its functions. Today, while I was trying to demonstrate this to a friend, and explain why you need to do this, I came across the following situation that I do not understand.
Consider the following code:
#include <math.h>
#include <stdio.h>
/* #define VARIABLE */
int main(void)
{
#ifdef VARIABLE
double a = 2.0;
double b = sqrt(a);
printf("b = %lf\n",b);
#else
double b = sqrt(2.0);
printf("b = %lf\n",b);
#endif
return 0;
}
If VARIABLE is defined, you need to link against libm as you would normally expect; otherwise you get the usual main.c:(.text+0x29): undefined reference to sqrt linking error indicating that the compiler cannot find the definition for the function sqrt. I was surprised to see that if I comment #define VARIABLE, the code runs fine and the result is correct!
Why is it that I need to link to libm when variables are used but I don’t need to do so when literal constants are used? How does the compiler find the definition of sqrt when the library is not linked? I’m using gcc 4.4.5 under linux.
As everyone mentions, yes it has to do with constant folding.
With optimizations off, GCC only seems to do it when
sqrt(2.0)is used. Here’s the evidence:Case 1: With the variable.
You can see that it emits a call to the
sqrtfunction. So you’ll get a linker error if you don’t link the math library.Case 2: With the Literal.
There’s no call to
sqrt. Hence no linker error.With optimizations on, GCC will do constant propagation in both cases. So no linker error in either case.