对 sqrt(或其他数学函数)的未定义引用

Undefined reference to sqrt (or other mathematical functions)

提问人:Waypoint 提问时间:3/10/2011 最后编辑:Marco BonelliWaypoint 更新时间:9/25/2020 访问量:114190

问:

我有这个简单的代码:

max = (int) sqrt (number);

在标题中,我有:

#include <math.h>

但应用程序仍然说未定义的引用。你看到这里有什么问题吗?看起来一切都应该没问题。sqrt

c 链接器错误 未定义引用

评论

1赞 Tommy 3/10/2011
哪个抱怨,链接器还是编译器?如果你能发布确切的错误,那可能会把事情弄清楚。
1赞 Waypoint 3/10/2011
编译器写了这个抱怨,问题是,应用程序甚至没有构建......
8赞 R.. GitHub STOP HELPING ICE 3/10/2011
问题不在于程序,而在于系统对 C 库的实现。它仍然遵循 1970 年代/1980 年代的传统约定,其中数学函数位于单独的库中,默认情况下不链接。
0赞 Nate Eldredge 2/11/2021
相关新闻: stackoverflow.com/questions/1033898/...

答:

123赞 paxdiablo 3/10/2011 #1

你可能会发现,无论你使用什么系统,你都必须与数学库链接,比如:

gcc -o myprog myprog.c -L/path/to/libs -lm
                                       ^^^ - this bit here.

包含标头可让编译器了解函数声明,但它不一定自动链接到执行该函数所需的代码。

如果做不到这一点,你需要向我们展示你的代码、编译命令和你运行的平台(操作系统、编译器等)。

以下代码编译和链接正常:

#include <math.h>
int main (void) {
    int max = sqrt (9);
    return 0;
}

请注意,某些编译系统取决于在命令行上给出库的顺序。我的意思是,他们可以按顺序处理库,并且只使用它们来满足序列中该点的未解析符号。

因此,例如,给定命令:

gcc -o plugh plugh.o -lxyzzy
gcc -o plugh -lxyzzy plugh.o

并且需要库中的某些内容,第二个可能无法按您的预期工作。在列出库时,没有未解析的符号需要满足。plugh.oxyzzy

当未解析的符号出现时,为时已晚。plugh.o

评论

0赞 user2284570 5/19/2015
@paxdiablo : 在 csqrt 的 μClibc 的情况下?
3赞 Kevin Bullaughey 7/10/2015
还要注意链接库的顺序。我发现我在命令行中过早地使用了 -lm,将其移动到末尾可以解决相关的错误消息。这似乎也依赖于 gcc 版本(一些旧版本并不介意)。
1赞 paxdiablo 3/14/2022
@Gabriel,我以为我的最后一部分(“请注意......”)涵盖了这一点。无论如何,它并不是必须排在最后,它只是不能排在任何完全需要它的东西之前。我的意思是,除了(假设并且是库中的单独对象)之外的所有内容都很好。当然,最后可能是最安全的地方(假设它不需要任何东西),但我今天感觉很迂腐:-)user_of_sin -lm user_of_cos user_of_xx -lprovider_of_xxcossincos
1赞 Gabriel Staples 3/14/2022
@paxdiablo,感谢您的澄清。是的,您的附加评论在迂腐上是正确的(意味着技术上是正确的),而我的评论实际上是正确的(意思是:在实际意义上作为一般经验法则是正确的)。我想不出任何将所有库放在最后不起作用的情况以及您想要的,尽管从技术上讲,正如您所说,库只需要紧跟在需要它的目标文件或源文件之后。
1赞 paxdiablo 3/14/2022
@Gabriel,没有问题。我同意所有库都应该出现在所有对象之后。我以前循环库依赖关系烧毁过,需要像这样的怪物来确保依赖关系得到解决。我甚至见过这样的情况:当库中的不同对象具有复杂的循环依赖关系时,多次需要这种往返。我不知道为什么 GNU 至少没有提供一个选项,让回到以前给定的库来满足新的未解析符号。-laaa -lbbb -laaald
31赞 krtek 3/10/2011 #2

我想你已经导入了 math.h#include <math.h>

因此,我能看到的唯一其他原因是缺少链接信息。您必须将代码与该选项链接。-lm

如果您只是想使用 gcc 编译一个文件,只需添加到命令行中,否则,请提供有关构建过程的一些信息。-lm

0赞 Mohamed Mnete 2/6/2017 #3

我遇到了同样的问题,但我只是通过在运行代码的命令后添加 -lm 来解决它。 例。 gcc 代码.c -lm

评论

2赞 grooveplex 7/29/2019
这与几年前发布的其他答案有何不同?
3赞 Hassan Rahman 7/10/2017 #4

只需在最后添加 c 源文件和 Makefile 中的 -lm 对我有用。#include <math.h>

    gcc -pthread -o p3 p3.c -lm

评论

0赞 Cloud Cho 10/20/2023
请分享“pthread”的原因。
3赞 Achal 7/28/2019 #5

这是我的观察,首先您需要将标头作为标头中声明的函数包含在头文件中。例如math.hsqrt()math.h

#include <math.h>

其次,如果您阅读 sqrt 的手册页,您会注意到这一行 Link with -lm。

#include <math.h> /* header file you need to include */

double sqrt(double x); /* prototype of sqrt() function */

Link with -lm. /* Library linking instruction */

但是应用程序仍然说对 sqrt 的未定义引用。你看到任何了吗 这里有问题吗?

编译器错误是正确的,因为你没有将你的程序与库链接,链接器无法找到引用,你需要显式链接它。例如lmsqrt()

gcc -Wall -Wextra -Werror -pedantic test.c -lm