如果我在C程序中包含<stdlib.h>或<stdio.h>,我在编译时不需要链接这些,但我必须链接到<math.h>,使用-lm与GCC,例如:

gcc test.c -o test -lm

这是什么原因呢?为什么我必须显式地链接数学库,而不是其他库?


当前回答

所有像stdio.h和stdlib.h这样的库都在libc中实现。或者libc。默认情况下被链接器链接。libc的库。因此在编译时自动链接并包含在可执行文件中。

但是math.h在libm中有它的实现。或者是libm。A是独立于lib。所以。默认情况下它不会被链接,您必须在GCC中编译程序时使用-lm标志手动链接它。

GNU GCC团队将其设计为与其他头文件分离,而默认情况下其他头文件会被链接,但math.h文件不会。

这里阅读第14.3项,如果你愿意,你可以全部阅读: math.h需要连接的原因

看看这篇文章:为什么我们必须在GCC中链接math.h ?

来看看用法:

使用图书馆

其他回答

所有像stdio.h和stdlib.h这样的库都在libc中实现。或者libc。默认情况下被链接器链接。libc的库。因此在编译时自动链接并包含在可执行文件中。

但是math.h在libm中有它的实现。或者是libm。A是独立于lib。所以。默认情况下它不会被链接,您必须在GCC中编译程序时使用-lm标志手动链接它。

GNU GCC团队将其设计为与其他头文件分离,而默认情况下其他头文件会被链接,但math.h文件不会。

这里阅读第14.3项,如果你愿意,你可以全部阅读: math.h需要连接的原因

看看这篇文章:为什么我们必须在GCC中链接math.h ?

来看看用法:

使用图书馆

stdlib.h和stdio.h中的函数在libc中有实现。所以(或libc。A用于静态链接),默认情况下链接到可执行文件中(就像指定了-lc一样)。可以指示GCC使用- nodlib或-nodefaultlibs选项避免这种自动链接。

math.h中的数学函数在libm中有实现。所以(或libm。A表示静态链接),默认情况下不链接libm。libm/libc的分裂是有历史原因的,但没有一个令人信服。

有趣的是,c++运行时libstdc++需要libm,因此如果使用GCC (g++)编译c++程序,将自动链接到libm。

请记住,C是一种古老的语言,而fpu是相对较新的现象。我第一次看到C语言是在8位处理器上,即使是32位整数运算也要做很多工作。许多实现甚至没有可用的浮点数学库!

即使在最初的68000台机器上(Mac、Atari ST、Amiga),浮点协处理器也常常是昂贵的附加组件。

要完成所有这些浮点运算,您需要一个相当大的库。数学运算会很慢。所以你很少使用浮动。你试着用整数或按比例的整数来做所有的事情。当你必须包括math.h时,你咬紧牙关。通常,您会编写自己的近似和查找表来避免这种情况。

Trade-offs existed for a long time. Sometimes there were competing math packages called "fastmath" or such. What's the best solution for math? Really accurate but slow stuff? Inaccurate but fast? Big tables for trig functions? It wasn't until coprocessors were guaranteed to be in the computer that most implementations became obvious. I imagine that there's some programmer out there somewhere right now, working on an embedded chip, trying to decide whether to bring in the math library to handle some math problem.

这就是数学不是标准的原因。许多或大多数程序都没有使用一个浮点数。如果fpu一直存在,浮点数和双精度浮点数的操作成本一直很低,毫无疑问,就会有一个“标准数学”。

我认为这有点武断。您必须在某个地方划清界限(哪些库是默认的,哪些库需要指定)。

它让你有机会用一个具有相同功能的不同产品来替代它,但我不认为这样做很常见。

我认为GCC这样做是为了保持与原始cc可执行文件的向后兼容性。我猜cc为什么这样做是因为构建时间——cc是为比我们现在的功率小得多的机器编写的。许多程序没有任何浮点数学运算,它们可能会将所有不常用的库从默认值中删除。我猜Unix操作系统的构建时间和与之配套的工具是驱动因素。

因为time()和其他一些函数是内置在C库(libc)中定义的,GCC总是链接到libc,除非你使用- ffrestanding compile选项。然而,数学函数存在于libm中,并不是由gcc隐式链接的。