一.
库是一种可执行代码的二进制形式,可以操作系统载入内存执行。Linux下库分为两种:动态库和静态库。

  • 静态库
    由.o文件以一种特定的方式打包成一个单独的文件,并且在链接生成可执行文件时,从这个文件中“拷贝”它所需要的内容到最终的可执行文件中。静态库的命名在Windows和Linux下都以.a为后缀。静态库的连接将整个函数库的数据整合进了目标代码,这样在编译后的执行程序不再需要外部函数的支持。但使用的静态库发生更新改变时,程序要重新编译。
    若要将源码f1.c,f2.c,...fn.c做成库文件,我们可通过以下命令制作成静态库:
    gcc -c f1.c
    gcc -c f2.c
    ...
    gcc -c fn.c
    ar -rcs libname.a *.o

  • 动态库
    动态库与静态库相似,但在连接时不需要将所有的内容都拷贝到可执行文件中,而是在程序执行到相关函数时才调用该库函数里相应的函数。动态库的命名在Linux下以.so为后缀。
    若要将源码f1.c,f2.c,...fn.c做成库文件,我们可通过以下命令制作成动态库:
    gcc -shared -fPIC -o libname.so f1.c f2.c ... fn.c

  • 动态库与静态库的区别在于:
    1.在编译时,静态链接将所有函数都编译进程序中,而动态链接是在程序运行时由操作系统帮忙把动态库调入到内存空间中使用。
    2.当同一个程序分别使用静态库,动态库两种方式生成两个可执行文件时,静态链接所生成的文件所占用的内存要远大于动态链接所生成文件占用的内存。

二.

  • C程序的编译

1.预处理
预处理是读取c源程序,对其中的伪指令和特殊符号进行“替代”处理,经过处理生成一个没有宏定义,没有条件编译指令,没有特殊符号的输出文件。
(1)宏定义指令如#define Name TokenString,#undef以及编译器内部建的一些宏。
(2)条件编译指令如#ifdef,#ifndef,#else,#enif等。
(3)头文件包含指令如#include "FileName"或者#include等。
通常用以下命令进行预处理,参数-E表示只进行预处理:
gcc -E f1.c -o f1.i
预处理后的f1.i还是c语言源代码,可以通过cat和vim命令查看代码:
vim f1.i

2.编译
编译程序所要做的工作就是通过词法分析和语法分析,在确定所有的指令都符合语法规则之后,将其翻译成等价的中间代码表示或汇编代码。
通常以下命令进行编译处理:
gcc -S f1.i>f1.s
可通过cat和vim命令进行查看:
cat f1.s

3.汇编
汇编过程实际上指把汇编语言代码翻译成目标机器指令的过程。对于被翻译器系统处理的每一个c语言源程序,都将经过这一处理得到相应的目标文件。目标文件中所存放的也就是与源程序等效的目标的机器语言代码。目标文件通常至少有两个段:

  • 代码段:该段中包含的主要是程序的指令。
  • 数据段:主要存放程序中要用到的各种常亮、全局变量、静态的数据。
    通常用一下命令进行汇编处理:
    gcc -c f1.s -o f1.o

4.链接
汇编程序生成的目标文件不能立即执行,其中还有许多未解决的问题。这些问题都需要通过链接程序的处理才能得已解决。链接程序的主要工作就是将有关的目标文件彼此连接,也即将在一个文件中引用的符号同该符号在另一个文件中的定义连接起来,使得所有的这些目标文件成为一个能被操作系统装入执行的统一整体,也就是可执行文件。链接方式可分为两种:

  • 动态链接
    1.name表示编译生成的可执行文件名;2.-I表示指定-I选项来指定头文件路径,pwd表示头文件路径;3.链接器通过-l选项来指定库文件(myname为库文件名);4.链接器默认到系统动态库路径下查找相应的库文件,找不到就出错,如果使用的动态库不在这些路径下,则使用-L选项指定路径,pwd1为动态库路径
    可通过以下方式进行动态链接:
    gcc main.c -o name -I 'pwd' -lmyname -L 'pwd1'
  • 静态链接
    如果动态库与静态库同时存在时优先使用动态库链接,若想使用静态库连接,一种方法是将动态库移除,另一种方法是在编译时加上链接选项-static,这样程序中所有的库都是用静态库链接了:
    gcc main.c -o name -I 'pwd' -lmyname -L 'pwd1' -static