`
dyx1024
  • 浏览: 114488 次
  • 性别: Icon_minigender_1
  • 来自: 西安
文章分类
社区版块
存档分类
最新评论

C核心技术手册(三十八)

 
阅读更多
18.3.1.4 连接

连接器将多个二进制的object文件连接成为一个可执行文件,在进程中,它完成使用外部引用来替换程序中本地对象的引用。连接器依据汇编器提供的符号表来完成这些工作。

此外,连接器必须为程序中使用的C标准库的函数添加代码,在连接的上下文中,一个库就是一系列object文件的集合,为了便于处理,它们以归档文件的形式被集合在一个独立的文件中。

大多数标准函数库通常在文件libc.a(其中后缀.a代表“archive),或者在一个共享的动态连接库libc.so( 其中后缀.so代表“shared object)。这些库通常在/lib/ /usr/lib中,或者在GCC默认的其他库目录中存放。

特定的函数存放在各自己的库文件中,比如标准库中的浮点数函数。为了示范如何连接这些库,让我们使用其他的变量来替代circle.cp的定义,在Example 1-1中,变量pi使用一个常量来初始化:

const double pi = 3.1415926536; // Pi is a constant

我们可以使用反正切函数来替换,如下:

const double pi = 4.0 * atan(1.0); // because tan(pi/4) = 1

当然我们要在源文件的头部添加指示符#include <math.h>,但函数atan() 没有在源代码中定义,也不在libc.a中,编译此circle.c文件,我们要使用-l选项来连接math库。

$ gcc -o circle -lm circle.c

math库的文件名为libm.a(在支持动态库的系统 上,GCC自动使用共享动态库libm.so,如果它可用,可以查看后面的“动态连接与共享object文件”一节来获取更多信息),其中前缀lib和或缀.a均为标准命名要求,当在命令行中基本名称跟随参数-l时,GCC自动扩展它们,例如m

通常,GCC在标准库所在目录中根据库文件名称来自动查找,例如/usr/lib。有三种连接一个库的方式,其中之一是给GCC提供全路径和库文件名,就像object文件一样,例如,假设库文件名为libmath.a,存放在/usr/local/lib中,如下的命令将使用GCC编译circle.c,然后连接器将结果文件circle.olibmath.a进行连接:

$ gcc -o circle circle.c /usr/local/lib/libmath.a

本例中,库的名子必须放置在使用它的源文件或object文件之后,这是因为连接器在命令中顺序地使用这些文件,并且不会返回到一个前面的库文件来解决一个后面对象中的引用。

第二种方不在GCC默认路径中连接的方式是使用-L选项来添加另一个库的目录来让GCC查找:

$ gcc -o circle -L/usr/local/lib -lmath circle.c

你可以使用多个-L选项来添加多个库目录,或者使用一个-L选项,后跟随一个目录列表;第三种方式是确保你所引用库的路径在环境变量LIBRARY_PATH中。

你可以直接传递选项参数到连接阶段,使用-Wl选项,后跟一个使用逗号分隔的列表,如下:

$ gcc -lm -Wl,-M circle.c circulararea.c > circle.map

命令行中的选项-Wl传递-M给连接器,指示连接器在标准输出上打印一个连接和一个内存印象文件。

-Wl后的列表必须以逗号开始,且不包含空格,如果不确定,你可认在同一个GCC命令行中使用多个-Wl选项,使用-v选项来查看连接器的结果。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics