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?

Original source

Related problems