Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/59.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么必须用C语言链接数学库?_C_Compilation_Math.h - Fatal编程技术网

为什么必须用C语言链接数学库?

为什么必须用C语言链接数学库?,c,compilation,math.h,C,Compilation,Math.h,如果我在C程序中包含或,我在编译时不必链接它们,但我必须使用带有gcc的-lm链接到,例如: gcc test.c -o test -lm 这是什么原因?为什么我必须显式链接数学库而不是其他库?stdio是标准C库的一部分,默认情况下,gcc将链接到该库 数学函数实现位于一个单独的libm文件中,默认情况下该文件未链接到该文件,因此必须将其指定为-lm。顺便说一下,这些头文件和库文件之间没有关系 我觉得这有点武断。您必须在某处画一条线(哪些库是默认库,哪些需要指定) 它让你有机会用一个具有相同

如果我在C程序中包含
,我在编译时不必链接它们,但我必须使用带有gcc的
-lm
链接到
,例如:

gcc test.c -o test -lm

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

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


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

我觉得这有点武断。您必须在某处画一条线(哪些库是默认库,哪些需要指定)

它让你有机会用一个具有相同功能的不同的替换它,但我认为这样做并不常见


编辑:(来自我自己的评论):我认为gcc这样做是为了保持与原始cc的向后兼容性。我猜cc为什么会这样做是因为构建时间——cc是为功率远低于现在的机器编写的。很多程序都没有浮点运算,它们可能会将所有不常用的库都从默认值中删除。我猜UNIX操作系统的构建时间和随之而来的工具是驱动力。

我想这是一种让根本不使用它的应用程序性能稍好一点的方法。这是我的想法

x86操作系统(我想象其他操作系统)需要在上下文开关上存储FPU状态。然而,大多数操作系统只是在应用程序首次尝试使用FPU后才保存/恢复此状态

除此之外,数学库中可能还有一些基本代码,在加载库时,这些代码会将FPU设置为正常的基本状态

因此,如果您根本不链接任何数学代码,这一切都不会发生,因此操作系统根本不必保存/恢复任何FPU状态,从而使上下文切换稍微更有效

不过只是猜测而已

编辑:对于一些评论,相同的基本前提仍然适用于非FPU情况(前提是要使没有使用libm的应用程序性能稍好一些)

例如,如果有一个软FPU,它在C的早期是likley,那么将libm分离可以防止大量大型(如果使用它,则速度较慢)代码被不必要地链接进来


此外,如果只有静态链接可用,那么类似的论点也适用,即它可以降低可执行文件的大小和编译时间。

中详细讨论了链接到外部库的问题。如果库是标准库(如stdio)的成员,则无需指定编译器(实际上是链接器)来链接它们

编辑:在阅读了其他一些答案和评论之后,我认为它链接到的和libm参考都有很多关于为什么两者是分开的

请注意,“libm.a”(数学库)中的许多函数在“math.h”中定义,但在libc.a中不存在。有些是,这可能会让人困惑,但经验法则是——C库包含ANSI规定必须存在的函数,因此如果只使用ANSI函数,则不需要-lm。相反,`libm.a'包含更多函数,并支持其他功能,如matherr回调和在发生FP错误时遵守若干替代行为标准。有关更多详细信息,请参见libm部分


stdlib.h
stdio.h
中的函数在
libc.so
中有实现(或
libc.a
用于静态链接),默认情况下链接到可执行文件中(好像指定了
-lc
)。可以指示GCC使用
-nostlib
-nodefaultlibs
选项避免此自动链接

math.h
中的数学函数在
libm.so
中有实现(或
libm.a
用于静态链接),默认情况下,
libm
不链接。libm/
libc
拆分有历史原因,但没有一个很有说服力

有趣的是,C++运行时<代码> LBSTDC++< /COD>需要代码> LBM< /Cuff>,所以如果用GCC编译一个C++程序(<代码> G++<代码> >,你将自动获得 LBM链接到.< /P> 如果我放置stdlib.h或stdio.h,我不必链接它们,但我必须在编译时链接:

stdlib.h
stdio.h
是头文件。为了方便起见,您可以将其包括在内。它们仅预测在适当的库中链接时可用的符号。这些实现在库文件中,这是函数真正存在的地方

包括
math.h
只是访问所有数学函数的第一步

此外,如果不使用
libm
的函数,即使您执行了
#include
操作,也不必链接到
libm
,这对于编译器来说只是一个关于符号的信息性步骤


stdlib.h
stdio.h
指的是
libc
中提供的函数,这些函数总是链接在一起,这样用户就不必自己做了。

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

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

要完成所有的浮点运算,您需要一个相当大的库。数学会很慢。所以你很少用花车。你试过了
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