118

我有以下代码(简化为这个问题的基本知识):

#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

但是,我编写了sinmain函数内部调用的各种测试程序,并且它们运行良好。我必须在这里做一些明显错误的事情 - 但它是什么?

4

4 回答 4

143

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

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

评论中,linuxD询问:

为什么对于sin()in <math.h>,我们是否需要-lm明确的选项?但是,不适合printf()in<stdio.h>吗?

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

该标准专门将“标准 C 库”例程与“标准 C 数学库”例程(第 277 页)分开。相关段落抄录如下:

标准 C 库

自动搜索标准 C 库 cc以解析外部引用。该库支持第 1 卷中定义的基本系统的所有接口,但数学例程除外。

标准 C 数学库

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

这种分离背后的原因受到许多因素的影响:

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

决定放入不同图书馆的压力-lm可能包括但不限于:

  1. 这似乎是减小 libc 大小的好方法,因为许多应用程序不使用嵌入在数学库中的函数。
  2. 它为数学库实现提供了灵活性,其中一些数学库依赖于较大的嵌入式查找表,而其他数学库可能依赖于较小的查找表(计算解决方案)。
  3. 对于真正大小受限的应用程序,它允许以非标准方式重新实现数学库(例如将其拉出sin()并将其放入自定义构建的库中。

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

于 2011-02-15T15:13:31.817 回答
79

无论如何,我添加了 -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

只是链接没有问题

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

于 2012-08-28T18:08:14.843 回答
42

您需要链接数学库 libm:

$ gcc -Wall foo.c -o foo -lm 
于 2011-02-15T15:12:10.477 回答
11

我有同样的问题,在我最后列出我的库后就消失了:gcc prog.c -lm

于 2012-01-13T08:19:45.440 回答