编译好了
#include <math.h>
int main(void) {
double i = sqrt(9.0);
}
Run Code Online (Sandbox Code Playgroud)
如果我将9.0更改为-9.0,那么我的编译器(GNU C)会给出关于'sqrt'的未定义引用的错误.
我期待sqrt函数返回NaN或异常.C库如何仅为非负参数定义sqrt?
发生这种情况是因为gcc可以在优化过程中使用内置函数来计算某些函数,包括sqrt在许多但不是所有情况下的编译时.如果是这种情况,它将不需要发出呼叫sqrt,因此不需要链接libm.
gcc文档有一个完整的内置列表,它说(强调我的):
其余功能用于优化目的.
GCC包含标准C库中许多功能的内置版本.即使指定了-fno-builtin选项,以_ builtin为前缀的版本也始终被视为与C库函数具有相同的含义.(参见C方言选项)许多这些功能仅在某些情况下得到优化 ; 如果它们在特定情况下未被优化,则会发出对库函数的调用.
如果我使用gcc -S并编译此代码并查看我们使用时发出的程序集(实例),sqrt(9.0)那么gcc将使用内置而不会发出对sqrt的调用,因为它将在编译时计算它.如果我们更改要使用的代码,sqrt(-9.0)它现在将发出(实例):
call sqrt
Run Code Online (Sandbox Code Playgroud)
这将需要与libm链接,修复将添加-lm到您的编译选项的末尾.
如果sqrt(-9)我们有域错误,如果转到C99草案标准部分那么7.12.7.5 sqrt函数第2段说(强调我的):
sqrt函数计算x的非负平方根.如果参数小于零,则会发生域错误.
如果我们回到7.12.1 错误处理条件,它会说:
[...]在域错误上,该函数返回一个实现定义的值; 如果整数表达式math_errhandling&MATH_ERRNO非零,则整数表达式errno获取值EDOM ; 如果整数表达式math_errhandling&MATH_ERREXCEPT非零,则引发''invalid''浮点异常.
因此,将设置errno和/或将引发浮点异常,这似乎是一种gcc决定优化效率不高的情况.
| 归档时间: |
|
| 查看次数: |
2374 次 |
| 最近记录: |