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

gcc test.c -o test -lm

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


当前回答

请记住,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一直存在,浮点数和双精度浮点数的操作成本一直很低,毫无疑问,就会有一个“标准数学”。

其他回答

stdio是标准C库的一部分,默认情况下,GCC将链接到该库。

数学函数实现在一个单独的libm文件中,默认情况下没有链接到该文件,因此必须指定它为-lm。顺便说一下,这些头文件和库文件之间没有关系。

请记住,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一直存在,浮点数和双精度浮点数的操作成本一直很低,毫无疑问,就会有一个“标准数学”。

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

如前所述,C库libc默认是链接的,该库包含stdlib.h、stdio.h和其他几个标准头文件的实现。只是补充一下,根据“GCC介绍”,C语言中基本“Hello World”程序的链接器命令如下所示:

ld -dynamic-linker /lib/ld-linux.so.2 /usr/lib/crt1.o
/usr/lib/crti.o /usr/libgcc-lib /i686/3.3.1/crtbegin.o
-L/usr/lib/gcc-lib/i686/3.3.1 hello.o -lgcc -lgcc_eh -lc
-lgcc -lgcc_eh /usr/lib/gcc-lib/i686/3.3.1/crtend.o /usr/lib/crtn.o

注意第三行中链接C库的选项-lc。

所有像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 ?

来看看用法:

使用图书馆