程序翻译过程

本文详细介绍了程序从源代码到可执行文件的编译过程,包括预处理、gcc命令的使用、动态链接和静态链接的区别,以及C标准库的作用。强调了动态链接节省资源但依赖外部库,静态链接虽浪费资源但提供更好的可移植性。
摘要由CSDN通过智能技术生成

前言

一天我突然忘了快速排序的代码实现,但我又没写笔记/博客,这时候我就开始后悔为什么当初没有写笔记、博客啊,于是我从现在每三天开始写一篇博客以便日后好复习。

我们写的源代码到可执行程序经历了哪些步骤?现在起我们开始一段代码的艺术之旅吧。

程序翻译过程

翻译过程gcc命令说明
预处理gcc -E test,c -o test,i宏替换,去注释,头文件展开,条件编译
编译gcc -S test.i -o test,s将c编译成汇编语言
汇编gcc -c test.s -o test,o将汇编语言翻译成二进制目标文件
链接gcc test.o -o my.exe生成可执行程序

这些命令看起有点复杂
怎么快速记忆这些gcc命令
-o的意思是给生成的文件重命名
★从预处理到汇编的 gcc 编译选项刚好是 ESc 键盘上的退出键
生成的文件后缀依次是 i,s,o 这个可以不用记 因为在Linux环境下并不关心 文件的后缀

后面我们编译程序的时候直接 gcc test.c -o test.exe或者 gcc -o test.exe test.c 一步到位

为什么是这个步骤?

机器只能识别二进制,为了书写方便才发明的汇编,因为汇编也不够方便,才发明的高级语言。当人们写汇编的时候,就需要先写二进制构成编译器来翻译汇编语言,但二进制的编译器维护不太方便,于是又有二进制的汇编编译器,写了一个汇编语言的汇编编译器,这称为编译器的自举。同理汇编到高级语言也是这样,先有低一级语言写成的高一级的编译器。不管怎样,历史上都是 二进制->汇编->高级语言,虽然可以从高级语言直接到二进制但是代价很大,没有二进制直接到高级语言的编译器。所以我们的源代码是一步一步的翻译到二进制的。

验证预处理阶段

原本只有13行的源代码经过预处理后变为800多行就是因为头文件展开了
在这里插入图片描述
经过条件编译后 v1 v2 条件下的代码都被编译器裁掉了 验证了在预处理阶段会进行条件编译
在这里插入图片描述

链接的故事

什么叫链接呢?

链接就是把我们的程序和库结合的过程。

我们可以通过 vim/usr/include/stidio.h 来查看stdio.h这个头文件
在这里插入图片描述
我们的C程序中,并没有定义“printf”的函数实现,且在预编译中包含的“stdio.h”中也只有该函数的声明,而没有定义函数的实现,那么,是在哪里实“printf”函数的呢?

c标准库

ldd 可执行文件 可以看到所依赖的库
最后的答案是:系统把这些函数实现都被做到名为 libc.so.6 的库文件中去了,在没有特别指

定时,gcc 会到系统默认的搜索路径“/usr/lib”下进行查找,也就是链接到 libc.so.6 库函数中去,

这样就能实现函数“printf”了,而这也就是链接的作用

在这里插入图片描述
Linux下默认安装好了c标准库,但在windows就没有

在这里插入图片描述
这个图就是我们以前在windows安装c标准库的过程

Linux下库分为两种,动态库和静态库

动态库和静态库

Linux:
动态库.so
静态库.a
咱们c 标准库就是动态库 libc.so.6 去掉前缀lib 后缀so.6 库名就是c
windos:
动态库.dll
以前我玩cf突然启动不了了,提示缺少.dll文件,我印象很深刻
静态库.lib

为什么要有链接

让开发站在巨人的肩膀上,提高开发效率

动态链接和静态链接

什么是动态链接和静态链接

简单来说
通过动态库的链接称为动态链接,通过静态库的链接称为静态库链接
具体我举个例子来说,小明要上高中了,但是想去上网,于是他就问学长哪里有黑网吧可以上网,学长说在学校的东门有一家网吧可以上网。于是小明周天安排上午学习,中午去上网,下午再完成作业。于是中午他就出校门去上网了。 这里学长相当于编译器,网吧相当于动态库,电脑相当于里面的方法,编译器告诉动态库的地址,程序执行到一定的过程就触发找对应的库了。还没上学期就知道网吧的地址了,也就是还没运行前就链接了。
在这里插入图片描述
共享动态库一但动态库丢失,所有动态链接的程序都无法执行了
编译器告诉动态库地址,程序去对应位置找称为动态链接

静态链接:
黑网吧被热心群众举报了,但是经过一年小明的努力,学习成绩是班上前几,于是他爸就给买了台笔记本安装在宿舍里。
在这里插入图片描述
在编译的时候,把库中的方法(电脑)拷贝(购买)到自己的静态库(宿舍电脑)中,自己的代码再和静态库链接这称为静态链接
这样不在关心任何的库,但是每次编译时都要拷贝方法到自己程序中,比较浪费资源
比如有十个程序都用到了printf 如果静态链接的话,printf就要加载十份到内存中

证明

  1. gcc默认形成的是动态链接通过file指令查看可执行程序的链接方式
    在这里插入图片描述
    2.静态链接编译后的程序更大
    验证的时候我们编译的时候加上 -static 这个命令选项
    在这里插入图片描述
    可能有的同学可能运行不起,因为Linux 默认是没有安装静态库的
    在这里插入图片描述

sudo yum install -y glibc-static
sudo yum install -y libstdc+±static
复制这两个语句就可以了 如果是管理员就不用加sudo

总结动态链接和静态链接的优缺点

动态链接静态链接
优点节省资源浪费资源
缺点动态库不能丢失可以丢失

静态链接的应用场景

既然静态链接这么浪费资源,那我们什么时候使用静态链接呢?
因为静态链接不依赖任何的动态库,所以可移植性很强,在对跨平台有较高要求的场景下,静态链接还是有用武之地的

谢谢观看

  • 16
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值