当前位置: 首页 > news >正文

程序编译的过程

一个程序是怎么变成可执行程序的?程序编译有哪些过程?都做了些什么事?

文章目录

  • 预处理 / 预编译
  • 编译
  • 汇编
  • 链接
  • 总结

预处理 / 预编译

源文件的编译有三个小过程,预处理,编译,汇编。最后经过链接,生成可执行程序。这如果细细地讲,那就是大学中的一门课《编译原理》,这是大学中最难的一门课之一。这里讲的没有那么细,但是也绝对够用了。
下面在Linux上演示各个过程,先随便写一点代码
在这里插入图片描述

观察预编译,使用下面的指令生成预编译之后的文件
在这里插入图片描述
在这里插入图片描述
下面进入预编译之后的文件,看看发生了什么。
在这里插入图片描述
足足多了八百多行,并且包含的头文件没有了,取而代之的是一个文件地址,我们尝试打开这个文件。
在这里插入图片描述
打开之后可以发现除了注释,其他基本上就和.i文件中多出的内容是一样的,这里就不再进行展示对比了。
并且我们还可以发现,除了展开头文件,还删除和注释和把宏替换为了指定的符号或者数字。
所以,我们就可以总结,编译阶段基本上是做了三件事:

  • 头文件的展开
  • 注释的删除
  • 宏替换

所以说,在预处理阶段完成的都是文本替换.

编译

输入下面的指令,可以将 .i 或者 .c 文件生成为编译后的文件,即.s文件。
在这里插入图片描述
进入.s文件
在这里插入图片描述
可以发现都是一些看不懂的汇编指令,所以我们也就可以清楚,在编译阶段,编译器将C语言代码转换为了汇编代码。
但是这个转换是非常复杂的,实际上做了四件事:语法分析,词法分析,符号汇总,语义分析。
这个符号汇总得说一下,后续在链接阶段用得到。
那么会对哪些符号进行汇总呢?其实也就那么几个。
全局变量,函数名。而局部的变量不会进行汇总,原因是局部变量在程序运行之后才进行创建,所以此时其实他们还并不存在。这就是符号汇总。

汇编

执行下面指令,进行汇编。
在这里插入图片描述
打开 .o 文件
在这里插入图片描述
可以发现都是机器才能看懂的二进制代码,所以说,在汇编阶段,将汇编代码转换为了二进制代码。
并且如果有两个源文件,比如test.c和add.c,这个时候这两个文件会生成自己的符号表,用来保存刚才编译汇总的那些符号,在test.c中定义的函数,会将这个函数以及它对应的地址放在这个文件符号表中,但是声明则不会。声明也会将函数放入符号表中,但是会给这个函数生成一个无效的地址。

所以,汇编阶段,就是将汇编代码转换为二进制代码,同时将编译阶段汇总的符号放在符号表中,后续链接阶段会用到这个符号表。

链接

输入下面指令,进行链接
在这里插入图片描述
这里就不需要添加什么其他的指令了,直接编译即可。编译后得到的文件就是可执行程序了,我们运行这个程序就能得到我们想要的结果了。
链接其实有两个动作:一是段表的合并,二是符号表的合并和重定位,各是什么意思呢?
合并段表:简单说一下,我们生成的add.o文件和test.o文件都是二进制的,在LInux中,它们符合elf格式。Linux下的可执行程序也是elf格式的,我们这里就是将相同格式的文件进行合并。
符号表的合并:多个符号表合并成一个符号表,每个符号选取其有效的地址。在链接阶段能不能使用这个符号,就取决于这个符号有没有一个有效的地址。
如果某个符号没有定义或者在两个源文件中都有定义,就会发生链接错误。
在C++的函数重载中,符号表中会根据函数的参数对函数名进行修饰,不用担心函数重名的问题。

总结

在预处理阶段,将头文件展开,进行注释的删除和宏替换。
在编译阶段,将C语言代码转换为汇编代码,进行:语法分析,词法分析,符号汇总和语义分析。
在汇编阶段,将汇编代码转换为二进制代码,并且进行生成符号表。
在链接阶段,生成可执行程序,合并段表并进行符号表的合成和重定位。

其他的一些小问题:
如果想深入了解,推荐书籍《程序员的自我修养》。

相关文章:

  • Spring由哪些模块组成
  • 单链表反转C语言代码
  • Visual Paradigm 17.X Crack
  • 【微服务】RabbitMQ高级篇
  • Dubbo-----------------项目整合和分析
  • ROS2 入门应用 工作空间
  • AOSP 8.0 系统启动之四ART虚拟机启动(一)
  • 1079 Total Sales of Supply Chain
  • 基于DemonSet方式收集容器日志输出实践
  • 牛客网:JZ65 不用加减乘除做加法(详解)
  • 设计模式:观察者模式
  • C/C++基础 memset()函数的用法
  • LeetCode 2176. 统计数组中相等且可以被整除的数对
  • 直线生成算法(DDA算法)
  • 10技术太卷我学APEX-导航卡Card
  • 红黑树插入结点
  • python入门 之 字典(六)
  • 通过python编写自定义尺寸和位置批量进行图像剪裁
  • 开发人员对需求的正确打开方式
  • SQLSERVER 快照隔离级别 到底怎么理解?
  • 电加热油锅炉工作原理_电加热导油
  • 大型电蒸汽锅炉_工业电阻炉
  • 燃气蒸汽锅炉的分类_大连生物质蒸汽锅炉
  • 天津市维修锅炉_锅炉汽化处理方法
  • 蒸汽汽锅炉厂家_延安锅炉厂家
  • 山西热水锅炉厂家_酒店热水 锅炉
  • 蒸汽锅炉生产厂家_燃油蒸汽发生器
  • 燃煤锅炉烧热水_张家口 淘汰取缔燃煤锅炉
  • 生物质锅炉_炉
  • 锅炉天然气_天燃气热风炉