编译器工作流程
编译的两种形式:编译和解释。
机器语言
- c语言——我们的编程语言到底是在和谁沟通的呢??相信很多人都认为编译语言在和计算机沟通的。但实际上,你回头再想,因为计算机的底层设计是二进制(高低电频),控制计算机的话应该是像1111000111111101001···(或者68 70 9F 43 00···)一大串的东西(机器语言)来表达我们的内容。所以人利用编译语言,编译语言和编译器沟通,编译器将编译语言变为二进制。
汇编语言
- 为了便于人的理解,出现了汇编语言(例如, push ebp mov ebp,es ),汇编语言和机器语言完全等价,唯一的优点就是加深了人的记忆。但是它太繁琐了,后来逐步被淘汰了。

C编程的基本策略
用程序把源代码文件转换为可执行文件(其中包含可直接运行的机器语言代码)。典型的C实现通过编译和链接两个步骤来 完成这一过程。编译器把源代码转换成目标代码*,链接器把中间代码和其他代码(包括库代码,启动代码)合并,生成可执行文件( 在window下则是.exe结尾的文件)*
?编译
- 目标代码文件

首先输入源代码xxx.c,接着编译器编译,然后现在的编译器比较聪明,如果没什么问题或者错误就生成目标代码xxx.obj,如下图
如果发现代码可以优化,就编译器优化,如下图;
如果发现代码有错误,在vs2022里面就会报错提示错误,以会出现C开头的错误,如下图
error是错误的意思,后面就是C2146错误提示,为什么是以C开头的呢?那是因为编译时利用到了一个编译组件,在vs2022里叫cl.exe,它就是一个程序,我们可以在vs2022程序里找到它。
- C 使用这种分而治之的方法方便对程序进行模块化,可以独立编译单独的模块,稍后再用链接器合并已编译的模块。通过这种方式,如果只更改某个模块,不必因此重新编译其他模块。
?链接
- 目标代码文件(xxx.obj)缺失启动代码(startup code)。启动代码充当着程序和操作系统之间的接口。例如,Windows和 Linux因为这些系统处理程序的方式不同。所以目标代码不相同。
- 目标代码还缺少库函数。几乎所有的C程序都要使用C标准库中的函数。使用了别人的库,你需要把别人的库加进来。例如,上次我们使用了 printf()函数,目标代码文件并不包含该函数的代码,它只包含了使用 printf()函数的指令。printf()函数真正的代码储存在另一个被称为库的文件中。库文件中有许多函数的目标代码。
- 链接器像一个正在拼图的人,各种各样的文件像他手中的拼图,他的目的是把拼图拼好。 链接器的作用是,把你编写的目标代码、启动代码和库代码这3部分合并成一个文件,即可执行文件。

如果在这时候出现错误,就是链接错误,在vs2022中以LINK开头,如下图
error是错误的意思,后面就是错误提示,为什么是以LINK开头的呢?同样的工作原理,如下图
- 注意这时候虽然链接出现错误,但是文件还是编译好了的,如下图

除了以上提及的编译错误和链接错误,我们以后会遇到更多的是粗心犯得逻辑错误,我们要训练这种找bug的能力,这是一种很重要的能力。
- 这就是编译器工作流程

其他补充
解释器,解释型语言边解释边执行,效率低,跨平台能力强。

逆向,既然我们通过源代码得到了软件,那么通过软件可以得到源代码吗?可以,这就是逆向——c语言的灵魂,它可以用来分析底层。

?进制
进制的概念
- 首先,我们先搞清楚:什么是进制。
这里我们先来说计数方法:不进位计数法,进位计数法。
不进位计数法表达非常麻烦,它必须实实在在让人看到这么多才能代表这个数量。比如,你现在在给别人展示1块钱,假如你要表现你非常有钱,展示100元,那就必须要拿100张1块钱,手握一大笔钞票,是不是很麻烦?类似的还有结绳记事法,所以在人类文明漫长的发展过程中,它肯定会被淘汰的嘛。
随着我们的智力增长中,我们找到了更好的计算方法,也就是进位计数法。进位计数法是用符号表达进制的一种方法,这就和我们的进制有关系了。
N进制:在计数中,一共有N个基本符号来表达0到N-1的数字内容,当到达N时,则进位后重新计数。以我们最熟悉的十进制为例,每逢十进一,比如10,我们在符号0,1,2,3,4,5,6,7,8,9中没有找到表达10的内容的东西,我们就进一位,用前面一个1表示一个10,后面0表示0个0,这样相乘相加110+00=10。
进制分为四种,二进制、八进制、十进制、十六进制。
进制的换算

- 十进制换算为二进制的方法:十进制以次除以2,将最后的商数和计算过程中的余数,依次链接起来即可。

如果觉得文章对你有帮助,点赞、收藏、关注、评论
版权声明:本文为chenchen205原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。