小解C语言文件编译过程【linux】
- 库
- 动态库
- 静态库
- C语言文件 程序编译过程
- 整体
- 预处理
- 编译
- 汇编
- 链接
- 动态链接
- 静态链接
- 两种方法对比
库
看到标题是文件编译过程
但是开头却是库,这可不是挂羊头卖狗肉,而是因为库也是代码不可缺少的一部分,并且在编译过程中需要进行处理。
那我们首先需要知道什么是库?
还记得我们写C语言时候,如果用到printf等函数,需要包上stdio的头文件吗
包上头文件后我们就能正常使用函数了
但是实际上,头文件中,只有函数的声明,而没有函数的实现和定义
那实现代码在哪呢?
就是在库中。
但是我们在写代码的过程中,并没有导入库
而导入库就是编译的过程中的部分了。
现在先来讲库的种类。
动态库
linux
动态库 .so
win
动态库:.dll
静态库
linux:
静态库 .a
windows
静态库:.lib
库的类型区分,主要体现在导入的方法中。
所以接下来进入编译过程的解读。
C语言文件 程序编译过程
大家都知道,对于计算机来说,只认识二进制码
那我们用了这么久的C语言,大家可能对C语言是如何转化成机器语言优点不太熟悉
所以这里就用linux系统,来带大家来认识一下C程序的编译过程
这里为了讲解就随便用了一个写了一个.C文件
#include<stdio.h>
#define max 10
int main()
{
printf("%d\n",max);
return 0;
}
整体
大致流程如图
接下来我们分别来看一下每个步骤:
预处理
预处理主要是将程序中的头文件展开以及宏定义和特殊符号进行处理
在linux中我们可以用
gcc -E test.c -o test.i
进行执行
这里的-E代表的意思是执行预处理指令
预处理结束后,会生成.i的文件
但是这里为了方便就直接重命名成test.i了
这里多了test.i文件
在test.i文件内部,我们能发现已经将stdio的头文件进行了展开
我们的写的代码还未进行处理
编译
编译:检查C语言程序语法,并将其转化为汇编语言。
可以用:
gcc -S test.i -o test.s
这个指令是要求test.c文件执行编译步骤。
结束后会生成.s文件
我们通过cat指令
能看到test.c内部是汇编语言
汇编
汇编:将汇编语言转化为二进制码
通过一下代码执行至汇编部分
gcc -c test.s -o test.o
但是将代码转化为计算机认识的二进制码以后,也还没结束
还有最后一步。
链接
链接:将二进制码与程序所需的库相链接
库已经在上面进行了解释
gcc test.o -o test
这里就是最后一步了,成功生成了test的可执行程序
但是其实,链接还有两种情况,记得我们上面讲的静态库和动态库吗
链接的作用是将库和文件链接
那既然有两种库,那就有两种链接方式。
动态链接
动态链接就是链接动态库
动态库链接方式其实就是我们上面的
gcc test.o -o test
就是说默认的链接方式就是动态链接
那动态链接是如何使用库的呢?
通俗的讲就是:需要用到库的时候自己去库里面找
留下了函数对应的接口,之后需要使用库的内容的时候,直接去原库中去寻找。
静态链接
静态链接是与静态库相对应的
当我们使用静态库的时候就进行静态链接。
我们可以用
gcc test.o -static -o test
这个方式来设置为静态链接
我们可以看看静态链接和动态链接文件大小
我们看到动态和静态大小差异巨大
这是因为:静态链接方式是将整个静态库写入至代码中
可以说这多出来的800000位的大小都是库的大小
两种方法对比
了解两种的链接方式后,会发现他们其实优缺点还是挺明显的
静态链接
优点:方便移植,不需要搭建库(毕竟整个库都在文件中)
缺点:浪费资源(读写资源,磁盘空间等)
静态链接
优点:节省资源
缺点:使用时需要下载动态库
但是实际上使用的时候,可以在一个项目中按照需求进行选择
做到静态和动态链接搭配使用