在gcc中-lm是什么意思?

Arm*_*maa 5 gcc

当我用编译一些C代码时gcc,需要添加-lm。例如,当我想fmax在程序中使用时,必须使用以下命令:

gcc myprogram.c -lm
Run Code Online (Sandbox Code Playgroud)

我不了解添加后会对我的程序产生-lm什么影响?什么-lm意思

谢谢。

小智 25

TLDNR:math.h 不是标准 C 库的一部分,因此您必须链接到它!

-l library在链接时搜索库。所述表示的libm,包含<math.h>中的库。有关更多信息,请参阅 两个 链接

@ luantkow的答案是确实不错,但长!如果您不想阅读,这里有一个简短的版本!¯\_(?)_/¯

  • @kk 答案中的信息有误吗?你能告诉我为什么吗? (3认同)
  • “math.h 不是标准 C 库的一部分”当然是。但它可能不是某个 gcc 端口使用的特定默认库的一部分。 (2认同)

lua*_*kow 6

假设您有以下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;
 }
Run Code Online (Sandbox Code Playgroud)

如果您尝试不带-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
Run Code Online (Sandbox Code Playgroud)

这是因为,链接器不知道该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
Run Code Online (Sandbox Code Playgroud)

您可以检查其中是否libm.a包含的定义fmax

$ nm /usr/lib/x86_64-linux-gnu/libm.a --defined-only | grep fmax
[...]
s_fmax.o:
0000000000000000 W fmax
[...]
Run Code Online (Sandbox Code Playgroud)

  • @aganm 你是否有机会使用“g++”而不是“gcc”编译代码?如果是,则代码被编译为“C++”而不是“C”,并且“C++”标准库默认需要“libm”。您可以在这里找到更多信息:/sf/answers/871739221/。如果没有的话,能分享一下你编译时使用的命令吗?我刚刚在 Ubuntu 21.04 上尝试过这个,并且需要 `-lm` 来链接可执行文件。 (2认同)