对“ sin”的未定义引用

我有以下代码(精简到这个问题的基本原理) :

#include<stdio.h>
#include<math.h>


double f1(double x)
{
double res = sin(x);
return 0;
}


/* The main function */
int main(void)
{
return 0;
}

当用 gcc test.c编译它时,我得到了下面的错误,而且我不知道为什么:

/tmp/ccOF5bis.o: In function `f1':
test2.c:(.text+0x13): undefined reference to `sin'
collect2: ld returned 1 exit status

然而,我已经编写了各种从 main函数内部调用 sin的测试程序,它们工作得非常完美。我一定是做错了什么,但是到底是什么呢?

167400 次浏览

你需要链接到数学库 libm:

$ gcc -Wall foo.c -o foo -lm

您已经使用对正确的 math.h 头文件的引用编译了代码,但是当您试图链接它时,您忘记了包含数学库的选项。因此,您可以编译您的。O 对象文件,但不生成可执行文件。

正如 Paul 已经提到的,在生成可执行文件的步骤中,添加“ -lm”以链接到数学库。

评论中,LinuxD问道:

为什么对于 <math.h>中的 sin(),我们需要显式地使用 -lm选项; 但是, 不是 <stdio.h>printf()吗?

因为这两个功能都是作为“单一UNIX规范”的一部分实现的。这个标准的历史很有趣,并且有很多名字(IEEE Std 1003.1,x/Open Portability Guide,POSIX,Spec 1170)。

这个标准,specifically separates out the "Standard C library" routines from the "Standard C Mathematical Library" routines (page 277)。相关的段落复制如下:

标准 C 库

The Standard C library is automatically searched by 解析外部引用。此库支持所有 第1卷中定义的基本系统的接口,除了 数学练习。

标准 C 数学库

这个库支持 基本系统数学例程,如第1卷中定义的。 cc选项 -lm用于搜索这个库。

这种分离的原因受到若干因素的影响:

  1. The UNIX 之战 led to increasing divergence from the original AT&T UNIX offering.
  2. UNIX 平台的数量增加了为操作系统开发软件的难度。
  3. 为软件开发人员定义最小公分母的尝试已经启动,即 叫做1988 POSIX
  4. 软件开发人员根据 POSIX 标准编程,在“符合 POSIX 的系统”上提供他们的软件,以达到更多的平台。
  5. UNIX 客户需要“符合 POSIX 的”UNIX 系统来运行该软件。

促使决定将 -lm放在另一个图书馆的压力可能包括在内,但不限于:

  1. 这似乎是降低 libc 大小的好方法,因为许多应用程序不使用嵌入在数学库中的函数。
  2. 它在数学库实现方面提供了灵活性,其中一些数学库依赖于较大的嵌入式查找表,而另一些则可能依赖于较小的查找表(计算解决方案)。
  3. For truly size constrained applications, it permits reimplementations of the math library in a non-standard way (like pulling out just sin() and putting it in a custom built library.

无论如何,现在标准的一部分是不自动包含为 C 语言的一部分,这就是为什么您必须添加 -lm

我遇到了同样的问题,在我最后列出了我的库之后,这个问题就消失了: gcc pro.c-lm

我仍然有 -lm的问题:

gcc -Wall -lm mtest.c -o mtest.o
mtest.c: In function 'f1':
mtest.c:6:12: warning: unused variable 'res' [-Wunused-variable]
/tmp/cc925Nmf.o: In function `f1':
mtest.c:(.text+0x19): undefined reference to `sin'
collect2: ld returned 1 exit status

我最近发现,如果您先指定 -lm,它就可以完成 没有的工作。命令很重要。您必须指定 -lm last,如下所示:

gcc mtest.c -o mtest.o -lm

连接没有问题。

因此,必须在最后指定库。