LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 3916|回复: 18

在linux用<math.h>的问题

[复制链接]
发表于 2006-2-13 19:04:08 | 显示全部楼层 |阅读模式
我想用标准库里的 pow() 函数,写了个程序如下

#include <stdio.h>
#include <math.h>

int main()
{
     int i;
     i = pow(2,2);
     printf("2x2 is %d", i);

     return 0;
}

但是gcc报错,

/tmp/ccSb96nM.o(.text+0x24): In function `main':
: undefined reference to `pow'
collect2: ld returned 1 exit status

我已经inlucde了<math.h>,为什么会出现这样的错误?
发表于 2006-2-13 21:11:55 | 显示全部楼层
编译时需要开发库的头文件, 连接时需要开发库的库文件。
math.h 对应的库是/lib/libm.so.6或/usr/lib/libm.so

这样: gcc main.c -lm
或:
gcc -c main.c
gcc -o main main.o -lm

不过通过使用/etc/ld.so.conf与/sbin/ldconfig对动态库进行缓存,好象可以略去-lm。
比如我运行你的例子用命令
[matt@localhost tmp]$ gcc main.c
[matt@localhost tmp]$ ./a.out
2x2 is 4[matt@localhost tmp]$

哪位可以具体谈谈其原理。
回复 支持 反对

使用道具 举报

发表于 2006-2-14 03:03:38 | 显示全部楼层
不够牛,谈不了
不过想问问除了math外其它还有什么需要加编译选项的库?
回复 支持 反对

使用道具 举报

发表于 2006-2-14 09:06:35 | 显示全部楼层
Post by MatthewGong
编译时需要开发库的头文件, 连接时需要开发库的库文件。
math.h 对应的库是/lib/libm.so.6或/usr/lib/libm.so

这样: gcc main.c -lm
或:
gcc -c main.c
gcc -o main main.o -lm

不过通过使用/etc/ld.so.conf与/sbin/ldconfig对动态库进行缓存,好象可以略去-lm。
比如我运行你的例子用命令
[matt@localhost tmp]$ gcc main.c
[matt@localhost tmp]$ ./a.out
2x2 is 4[matt@localhost tmp]$

哪位可以具体谈谈其原理。

连接器的原理涉及到编译原理、操作系统、计算机体系结构三个方面的知识,说起来比较复杂。但说通俗一点,可以这样理解:编译时只是指定了到那个动态链接库中去解析某个特定的记号。如gcc -c main -lm指定了到动态库libm.so中去动态解析符号。真正完成动态链接过程的是动态链接器ld-linux.so。这个动态链接器的名字可以用ldd命令看到。当程序在运行时需动态要解析一个记号,它就把动态库的名字和要解析的符号传递给动态链接器,由动态链接器去负责去查找这个动态库。/det/ld.so.conf就是动态链接器查找动态库的路径。为了提高效率,真正使用的是动态库的缓存ld.so.cache。这个ld.so.cache由命令ldconfig进行更新。所以每次升级动态库后,都要执行ldconfig来更新缓存。不然就会出现找不到动态库的问题。
回复 支持 反对

使用道具 举报

发表于 2006-2-14 14:03:24 | 显示全部楼层
kj501讲了动态库运行时的工作原理。
那么编译时省略-lm也应用了这个原理吧。
对应的,静态库(.a)就不可省略-lXXX了吧。
回复 支持 反对

使用道具 举报

发表于 2006-2-14 14:09:55 | 显示全部楼层
Post by kj501
连接器的原理涉及到编译原理、操作系统、计算机体系结构三个方面的知识,说起来比较复杂。但说通俗一点,可以这样理解:编译时只是指定了到那个动态链接库中去解析某个特定的记号。如gcc -c main -lm指定了到动态库libm.so中去动态解析符号。真正完成动态链接过程的是动态链接器ld-linux.so。这个动态链接器的名字可以用ldd命令看到。当程序在运行时需动态要解析一个记号,它就把动态库的名字和要解析的符号传递给动态链接器,由动态链接器去负责去查找这个动态库。/det/ld.so.conf就是动态链接器查找动态库的路径。为了提高效率,真正使用的是动态库的缓存ld.so.cache。这个ld.so.cache由命令ldconfig进行更新。所以每次升级动态库后,都要执行ldconfig来更新缓存。不然就会出现找不到动态库的问题。

计算机体系是不是专指硬件体系结构的呢?动态链接应该不涉及硬件的吧。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2006-2-14 14:23:55 | 显示全部楼层
多谢大家解答!
虽然原理还不是很明白,但是我这初学者,知其然不知其所以然已经很开心了。
谢谢!
回复 支持 反对

使用道具 举报

发表于 2006-2-15 09:48:41 | 显示全部楼层
Post by MatthewGong
kj501讲了动态库运行时的工作原理。
那么编译时省略-lm也应用了这个原理吧。
对应的,静态库(.a)就不可省略-lXXX了吧。

编译时不能省略-lm,不然编译时会出错。
回复 支持 反对

使用道具 举报

发表于 2006-2-15 10:16:00 | 显示全部楼层
Post by Illidan
计算机体系是不是专指硬件体系结构的呢?动态链接应该不涉及硬件的吧。

计算机体系结构指的就是cpu硬件的体系结构,说通俗点就是在讲cpu是如何设计的。链接过程会在多方面受到计算机体系结构的影响和制约。如一个cpu的体系结构决定了运行在这种体系结构上的指令格式,而链接器在链接时常常要处理包含在指令中的地址,对其进行重定位。自然要求链接器要能正确识别特定体系结构的指令格式。地址的保存也会存在大端小端的问题。这也是要受到体系结构影响的。还有应用程序二进制接口ABI规范以及虚拟内存的管理。这一系列的问题都会对连接器的工作造成制约。事实上cpu体系结构对底层软件的影响是决定性的。不理解好计算机的体系结构,就没法写出好的系统软件。
回复 支持 反对

使用道具 举报

发表于 2006-2-15 10:17:36 | 显示全部楼层
Post by MatthewGong
kj501讲了动态库运行时的工作原理。
那么编译时省略-lm也应用了这个原理吧。
对应的,静态库(.a)就不可省略-lXXX了吧。

编译时不能省略-lm,不然编译时会出错。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表