C语言 为什么要链接math库
一、相关问题
正常的 C 程序,像是使用了 stdio 或是 stdlib 等库的程序在编译时都是直接编译的,不需要指定任何链接选项。
例如:
gcc test.c -o test
但是如果程序中使用了 math 库,直接编译会报如下错误:
/usr/bin/ld: /tmp/cc1aTRz1.o: in function `main':
test.c:(.text+0x5c): undefined reference to `sqrt'
collect2: error: ld returned 1 exit status
想要正确编译,就必须在其后加上 -lm 选项
例如:
gcc test.c -o test -lm
可是,为什么呢?为什么要手动链接呢?我在 StackOverflow 上找到了一些答案。
二、简答
stdli.h
和 stdio.h
中的函数在 libc.so
(或静态链接 libc.a
)中有具体实现,它们是默认链接到你的可执行文件的(就像指定了 -lc
选项一样)。通过使用 -nostdlib
或 -nodefaultlibs
选项可以避免 GCC 自动链接。
math.h 中的数学函数在 libm.so
(或静态链接 libm.a
)中有具体实现,但是 libm 并不是像 libc 一样默认链接的。关于 libm 和 libc 的不同,有一些荒谬的历史原因。
有趣的是,C++ 的 libstdc++
需要 libm,所以如果使用 C++ 编译器(G++),就可以自动链接 libm。
三、荒谬的历史
因为 C 是个“古老”的语言,浮点运算器
也是相对来说最近才出现并流行的。很久以前 C 语言在 8 位运算器上进行 32 位的 数值运算。这些实现很大一部分甚至没有可用的浮点数学库。
甚至是最早的 68000 机器,其浮点运算器也是相当昂贵的附加产品
。
在浮点运算器未出现前,如果要实现所有的浮点运算,需要一个十分庞大的库,并且计算效率很低
。所以人们很少使用浮点数。人们尝试使用整数或缩放整数来模拟浮点运算
,不到万不得已不会使用 math.h。通常为了避免这一情况发生,人们都有自己的近似值和查找表。
这种权衡存在了很久。有时有些数学库的名字叫做 “fastmath”。数学库的最优解决方案是什么?精确无误但效率低下的?还是不精确但效率高的?亦或是庞大的三角函数表?直到浮点运算器的出现和流行,这些问题才得以解决。浮点运算器一定会有误差,但科学及工程计算仍大量的依靠浮点运算器。只是在程序设计时就必需考虑精确度问题。
可以说,如果浮点运算器比 C 语言出现的早,或者浮点运算操作很简单的话,就不会出现这样尴尬的情况,肯定会有一个 “stdmath” 库。
参考:
若你喜欢我的文章,欢迎关注
👇点赞
👇评论
👇收藏
👇 谢谢支持!!!