当我使用gcc
编译一些c代码时,它会添加-lm
。
例如,当我想在我的程序中使用fmax
时,必须使用以下命令:
gcc myprogram.c -lm
通过添加-lm
,我不明白我的计划会发生什么? -lm
是什么意思?
感谢。
答案 0 :(得分:4)
假设您拥有main.c
文件:
#include <math.h>
#include <stdio.h>
float my_foo(float a, float b)
{
return fmax(a, b);
}
int main()
{
printf("%f\n", my_foo(4.5, 3.1));
return 0;
}
如果您尝试编译时没有-lm
标记,则会收到undefined reference error
:
main.o: In function `my_foo':
main.c:(.text+0x1d): undefined reference to `fmax'
collect2: error: ld returned 1 exit status
这是因为链接器不知道fmax
函数的任何实现。你必须提供它。
在gcc main中,您可以找到-llibrary
标志的以下说明:
在链接时搜索名为library的库。(第二种方法是将库作为单独的参数,仅用于POSIX,不建议使用。)
在您编写此选项的命令中,它会有所不同;链接器按照指定的顺序搜索和处理库和目标文件。因此,foo.o -lz bar.o在文件foo.o之后但在bar.o之前搜索库z。如果bar.o引用z中的函数,则可能无法加载这些函数。
链接器搜索库的标准目录列表,该库实际上是名为liblibrary.a的文件。然后链接器使用此文件,就好像它已按名称精确指定一样。
搜索的目录包括几个标准系统目录以及您使用-L指定的任何目录。
通常,以这种方式找到的文件是库文件---存档文件,其成员是目标文件。链接器通过扫描存档文件来处理存档文件,以查找已定义但尚未定义的符号的成员。但是,如果找到的文件是普通的目标文件,则以通常的方式链接。 使用-l选项和指定文件名之间的唯一区别是-l使用lib和.a包围库并搜索多个目录。
看起来我有/usr/lib/x86_64-linux-gnu/libm.a存储的libm.a文件:
$ find /usr/lib -iname libm.a
/usr/lib/x86_64-linux-gnu/libm.a
您可以检查libm.a
是否包含fmax
的定义:
$ nm /usr/lib/x86_64-linux-gnu/libm.a --defined-only | grep fmax
[...]
s_fmax.o:
0000000000000000 W fmax
[...]
答案 1 :(得分:2)
TLDNR:math.h不是标准C库的一部分,因此您必须链接到它!
-l <em>库在链接时搜索库库。 m 代表 libm ,该库包含
@ luantkow's答案的确不错,但是很长!如果您不想阅读,这是一个简短的版本! ¯\ _(ツ)_ /¯