编译的过程
在正式开始之前首先对编译和链接进行一个整体的了解
1.预处理阶段
a.预处理工作:展开头文件,去注释,宏替换和删除
gcc -E test.c -o test.i
-E表示程序开始翻译,当执行完预处理就停下来
-o表示将预处理后形成的临时文件(名字任取)
在vim底行模式下输入:vs+文件名即可打开多个文件
安装gcc:sudo yum -y install gcc
b.外部定义宏参数
gcc test.c -DSHOW//在外部给test.c定义宏SHOW
gcc+文件名不加任何选项就是直接将源代码翻译成可执行程序,生成的可执行程序默认名称为a.out
外部定义的宏只在a.out中生效,并没有改变test.c文件
2.编译(生成汇编)
gcc -S test.i -o test.s
-S表示开始翻译程序,当执行完编译过程就停下来
此时再用vim打开就可以到test.c翻译成的汇编代码
3.汇编(生成不可执行的可重定向二进制目标文件)
gcc -c test.s -o test.o
-c表示开始执行程序的翻译,当完成汇编过程就停下来
经过汇编以后,我所写的代码已经从自然语言转换成了二进制的机器语言,可以看到此时文件中的内容我们不认识
在终端输入od命令,可以发现test.o文件中放着的是各种数字组合
4.链接(生成可执行的目标文件)
gcc test.o
链接完以后就生成了可执行程序
可执行程序默认名称为a.out,但我也有自主命名权
动/静态链接
首先要清楚,我所写的代码和库是两回事,我所写的代码是由我声明由我定义的,而库则是别人提供的我只需要调用即可。
从预处理到编译一直都是在翻译我写的代码,也就是说在链接之前,我的test.c文件中只有printf等C标准库函数的调用,没有对应的实现。而链接过程就是将我写的代码和库链接起来(本质是让我写的代码和库产生关联)。
注意:我们所包含的头文件中并没有函数的实现,只有函数的声明
感性的认识动/静态链接
动态链接
假设你是一个很爱上网的少年,但是你家没有电脑,不过你知道在你家周围有个网吧叫精英网络,你每次有上网的需要时就要从家里走路到网吧然后让网管给你开一个机子。你从你家到网吧并让网管给你开机子这个过程就类似于动态链接。动态库并不存在于我的程序中,但是我知道这个动态库的地址,每当我有使用动态库的需求时就能根据这个地址去找到这个动态库。
静态链接
你觉得每次都要出去上网太不安全了,所以你就和你的家长商量买一台电脑。你的家长十分的开明,他们把你在网吧经常用的那台电脑买回来放到了你的房间。此后你再有上网需要的时候就不必再跑到网吧了,而是直接在房间里就可以使用。那么你家长从网吧买回那个你经常使用的电脑让你以后不用再去网吧了,这个过程就相当于静态链接。所谓静态链接就是每次我需要使用库中的函数时,直接从库中拷贝一份。
动/静态链接的优缺点
动态链接
如果我一直去网吧上网,那么有这几个问题需要我考虑:
1.如果这个网吧要升级配置,会不会影响我
2.如果这个网吧被取缔了,影响我吗
3.去网吧是不是要耗费大量时间
网吧升级需要耗费时间,期间上不了网,如果网吧被查封以后可能都不上不了网了。而且每次走到网吧去还要耗费大量时间。但是我只要带钱就能上网(黑网吧不要身份证)。
动态链接的优势在于:
1.生成的可执行程序小(电脑不在我家放着,当然不占我家空间)
2.加载到内存中的速度快
3.节省资源(包括磁盘,网络,内存)
缺点在于:过于依赖动态库,导致程序的可移植性差。(因为我没电脑只能去网吧,所以很依赖网吧)
静态链接
当我有了电脑以后,网吧是否升级/查封我已经不关心了,我在家就能玩电脑也就没有赶路的时间损耗了。但是一台台式电脑放在我的房间里占用的空间太多了。
静态链接的优势在于:
不受库的影响,可移植性比较好,没有与库链接的过程,节省时间
缺点:
如果多个文件都用了同一个库函数,就要拷贝多次,代码冗余量高
因为有大量的拷贝内容,所以静态链接形成的可执行程序比较大
区分动/静态链接
查看链接属性
file+可执行程序文件名
知道是动态链接以后还可以使用ldd+可执行程序文件名
来查看所依赖的动态链接库
动态链接库:前缀为lib,后缀为.so
静态链接库:前缀为lib,后缀为.a
libc.so.6去掉前缀lib和后缀.so以及版本号.6,最后只剩下c,所以这个是C标准库
指定静态链接
当我不指定时Linux将自动采用动态链接,如果要使用动态链接就要在编译生成可执行文件时加上static选项gcc test.c -o mytest -static
如果系统中没有动态库只有静态库,那么即使不指定-static,生成的可执行文件也是动态链接的
总结
1.下载一个C语言程序,是否需要额外下载C标准库?
系统通常会自带动态库,动态库文件基本差别不大,而静态链接的程序不用依赖静态库,所以下载C语言程序不用额外下载C标准库
2.静态链接所拷贝的代码,从哪里来?
3.补充一点
在Windows下动态库是.lld,静态库是.lib