以下代码在Linux上抛出未定义的符号错误。
$ cat rms.c
/* sqrt example */
#include <stdio.h>
#include <math.h>
int main ()
{
double param, result;
param = 1024.0;
result = sqrt (param);
printf ("sqrt(%lf) = %lf\n", param, result );
return 0;
}
$ gcc rms.c
/tmp/ccaWecFP.o(.text+0x24): In function `main':
: undefined reference to `sqrt'
collect2: ld returned 1 exit status
如果我用(double)16替换sqrt()的参数,那么程序正在编译并执行。为什么在第一种情况下抛出错误。
答案 0 :(得分:4)
这是链接器错误。
链接器缺少sqrt()
的实现。它位于库libm
。
通过应用-lm
选项告诉GCC添加它。
答案 1 :(得分:3)
数学库或sqrt()
中提供了libm
的实施。
您必须将您的程序链接到数学库,如:
gcc rms.c -lm
一个自然的问题是,我怎么知道这个?答案在于联机帮助页。如果我做“man sqrt”,我会看到以下内容。请注意,概要中提供链接指令。。
SYNOPSIS
#include <math.h>
double sqrt(double x);
Link with -lm.
答案 2 :(得分:2)
答案 3 :(得分:1)
正如其他答案所说,您需要传递-lm
才能链接到包含sqrt
符号的库。
它与常量参数一起使用的原因是因为允许将sqrt
实现为内置函数。当GCC看到一个使用常量参数调用的内置函数时,它可以在编译时计算结果,而不是向库中的外部函数发出调用。
答案 4 :(得分:0)
这里的其他答案讨论链接错误;我将添加一个答案,说明如果将param
替换为常量,为什么结果正确。
GCC进行了优化,用内置等效项(例如sqrt
)和函数的常数参数(例如16.0
)替换了具有这些计算结果的函数(例如4.0
)
这是不断折叠的一种形式。