c - sqrt 仅在参数为非负时定义

标签 c gcc math.h sqrt

这样编译很好

#include <math.h>

int main(void) {
    double i = sqrt(9.0);
}

如果我将 9.0 更改为 -9.0,那么我的编译器 (GNU C) 会给出一个关于对“sqrt”的 undefined reference 的错误。

我原以为 sqrt 函数会返回 NaN 或异常。 C 库如何只为非负参数定义 sqrt?

最佳答案

这是因为 gcc 可以在优化过程中使用 内置函数 在编译时计算某些函数,包括 sqrt所有情况。如果是这种情况,它将不需要发出对 sqrt 的调用,因此不需要链接到 libm

gcc 文档有一个 complete list of builtins ,它说(强调我的):

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.

如果我使用 gcc -S 编译此代码并查看我们使用 sqrt(9.0) 时发出的程序集 ( live example ) > 然后 gcc 将使用一个内置函数并且根本不会发出对 sqrt 的调用,因为它将在编译时计算它。如果我们将代码更改为使用 sqrt(-9.0),它现在将发出( live example ):

call    sqrt

这将需要与 libm 链接,修复方法是将 -lm 添加到编译选项的末尾。

sqrt(-9) 的情况下,我们有一个域错误,如果转到 C99 草案标准部分 7.12.7.5 sqrt 函数 2 段说(强调我的):

The sqrt functions compute the nonnegative square root of x. A domain error occurs if the argument is less than zero.

如果我们回到 7.12.1 Treatment of error conditions 它说:

[...] 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.

因此将设置 errno 和/或将引发 float 异常,这似乎是 gcc 决定的情况优化效率不高。

关于c - sqrt 仅在参数为非负时定义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20156285/

相关文章:

C++ - 外部整数( double )

c - 使用 pow() 函数在 C 中抛出 undefined reference 错误

C 链表 : How do I save the 'Head' in a 'Temp' var so I don't have to traverse backwards each time

c - 套接字编程中的 htons() 函数

c - 在两点之间用新位替换旧位

c++ - GCC C++11 删除移动可分配类的复制分配会阻止 std::sort 编译?

c - "Expected ' ) ' to match this ' ( ' "当添加 & 到函数原型(prototype)时

gcc - 在 x64 模式下为 _mm_movemask_epi8 内部生成不必要的指令

字符 *a, *b; (b-a) 是什么类型,我该如何打印它?

math - 编译和链接 KISSFFT