未定义的引用“罪”

我有下面的代码(剥离到这个问题的基本知识):

#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 

但是,我已经写了各种testing程序,从main函数内部调用sin ,而且完美的工作。 我必须在这里做一些明显的错误 – 但是这是什么?

您已经编译了正确的math.h头文件引用的代码,但是当您尝试链接它时,您忘记了包含math库的选项。 因此,你可以编译你的.o目标文件,但不能build立你的可执行文件。

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

在评论中 , linuxD问:

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

因为这两个函数都是作为“单一UNIX规范”的一部分来实现的。 这个标准的历史很有意思,并且被许多人所知(IEEE Std 1003.1,X / Open Portability Guide,POSIX,Spec 1170)。

本标准特别将“标准Cmath库”例程(第277页)中的“标准C库”例程分开 。 相关的文章复制如下:

标准C库

标准C库由cc自动search来parsing外部引用。 该库支持第1卷中定义的基本系统的所有接口,math例程除外。

标准Cmath图书馆

该库支持第1卷定义的基本系统math例程-lm选项-lm用于search此库。

这种分离背后的原因受到以下因素的影响:

  1. UNIX战争导致了与最初的AT&T UNIX产品不同的分歧。
  2. UNIX平台的数量增加了开发操作系统软件的难度。
  3. 为软件开发者定义了最低公分母的尝试, 被称为1988 POSIX 。
  4. 软件开发人员根据POSIX标准进行编程,在“符合POSIX的系统”上提供软件,以便达到更多的平台。
  5. UNIX客户要求“符合POSIX的”UNIX系统来运行软件。

投入到决定将其放入不同图书馆的压力可能包括但不限于:

  1. 这似乎是保持libc大小不变的好方法,因为许多应用程序不使用math库中embedded的函数。
  2. 它提供了math库实现的灵活性,其中一些math库依赖于较大的embedded式查找表,而另一些可能依赖较小的查找表(计算解决scheme)。
  3. 对于真正大小受限的应用程序来说,它允许以非标准方式重新实现math库(比如只提取sin()并将其放入一个定制的库中。

在任何情况下,它现在都是标准的一部分,不会被自动包含在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,它就不起作用。 订单很重要:

 gcc mtest.c -o mtest.o -lm 

只是没有问题的链接

所以你必须在后面指定库。

你需要链接到math库libm:

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

我有同样的问题,最后列出我的图书馆后,去掉了:gcc prog.c -lm