如果我在C程序中包含<stdlib.h>或<stdio.h>,我在编译时不需要链接这些,但我必须链接到<math.h>,使用-lm与GCC,例如:
gcc test.c -o test -lm
这是什么原因呢?为什么我必须显式地链接数学库,而不是其他库?
如果我在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 ?
来看看用法:
使用图书馆
其他回答
这是个bug。你不必再显式地指定-lm了。也许如果有足够多的人抱怨,它就会被修复。(我并不真的相信这一点,因为坚持这种区别的维护者显然非常固执,但我希望如此。)
这里给出一个解释:
因此,如果您的程序使用数学函数并包含math.h,那么您需要通过传递-lm标志显式地链接数学库。这种特殊分离的原因是数学家对计算数学的方式非常挑剔,他们可能希望使用自己的数学函数实现而不是标准实现。如果数学函数集中到libc中。A这是不可能的。
(编辑)
不过,我不确定我是否同意这一点。如果你有一个库,它提供了,比如说,sqrt(),并且你在标准库之前传递它,Unix链接器会获取你的版本,对吗?
在《GCC介绍-与外部库链接》中有关于链接到外部库的详细讨论。如果一个库是标准库(如stdio)的成员,则不需要指定编译器(实际上是链接器)来链接它们。
在阅读了一些其他的回答和评论后,我认为libc。参考文献和它链接到的libm参考文献都有很多关于为什么两者是分开的。
Note that many of the functions in 'libm.a' (the math library) are defined in 'math.h' but are not present in libc.a. Some are, which may get confusing, but the rule of thumb is this--the C library contains those functions that ANSI dictates must exist, so that you don't need the -lm if you only use ANSI functions. In contrast, `libm.a' contains more functions and supports additional functionality such as the matherr call-back and compliance to several alternative standards of behavior in case of FP errors. See section libm, for more details.
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一直存在,浮点数和双精度浮点数的操作成本一直很低,毫无疑问,就会有一个“标准数学”。