sqrt is only defined when argument is nonnegative
c, gcc, math.h, sqrt
Solution
This is happening because `gcc` can use builtin functions during the optimization process to compute certain functions including `sqrt` at compile time in many but not all cases. If that is the case it will not need to emit a call to `sqrt` and therefore will not need to link against `libm`.
The gcc documents have a complete list of builtins, and it says (emphasis mine):
The remaining functions are provided for optimization purposes.
GCC includes built-in versions of many of the functions in the standard C library. The versions prefixed with _builtin are always treated as having the same meaning as the C library function even if you specify the -fno-builtin option. (see C Dialect Options) Many of these functions are only optimized in certain cases; if they are not optimized in a particular case, a call to the library function is emitted.
If I compile this code with `gcc -S` and look at the assembly emitted(live example) when we use `sqrt(9.0)` then `gcc` will use a builtin and not emit a call to sqrt at all since it will compute it at compile time. If we change the code to use `sqrt(-9.0)` it will now emit(live example):
call sqrt
which will require linking with libm, the fix would be to add `-lm` to the end of your compile options.
In the case of `sqrt(-9)` we have a domain error, if go to the C99 draft standard section `7.12.7.5` The sqrt functions paragraph 2 says (emphasis mine):
The sqrt functions compute the nonnegative square root of x. A domain error occurs if the argument is less than zero.
If we go back to `7.12.1` Treatment of error conditions it says:
[...] On a domain error, the function returns an implementation-defined value; if the integer expression math_errhandling & MATH_ERRNO is nonzero, the integer expression errno acquires the value EDOM; if the integer expression math_errhandling & MATH_ERREXCEPT is nonzero, the ‘‘invalid’’ floating-point exception is raised.
so either errno will be set and/or a floating point exception will be raised which seems like a case where `gcc` would decided it is not efficient to optimize.
Problem
This compiles fine ``` #include <math.h> int main(void) { double i = sqrt(9.0); } ``` If I change 9.0 to -9.0, then my compiler (GNU C) gives an error about an undefined reference to 'sqrt'. I was expecting the sqrt function to return NaN or an exception. How does the C library only define sqrt for non-negative arguments?