2023-03-17 C语言深度解析(1):编译的详细过程

01_编译的详细过程

我们这里虽然介绍的是c程序的编译过程,但是实际上所有编译型语言的编译过程,大致是类似的

编译的四个过程

我们平时编译时,不管是通过IDE图形界面来编译的,还是通过命令行来编译的,我们感觉编译一下就完成了,然后就得到了你要的针对某OS和某CPU的二进制可执行文件
(机器指令的文件),但是实际上中间隐藏了四个过程,这四个过程被默默的处理了。编译四个过程预处理、编译、汇编、链接

四个过程中的“编译”,特指其中的某个过程,这四个过程合在一起,我们也统称为编译,所以“编译”二字到底指的是第二个过程,还是全部过程的统称,这个就要看说话的“语境”了。其实统称的“编译”,完整的称法应该叫“编译链接”,只是简称为编译而已。

如果这四个过程是一次性编译完成的,这个四个过程分别会产生相应的文件,只不过中间产生的文件都是过渡性的临时文件,使用完成后就会被删除。

编译过程

第1步:预编译(预处理)

之所以叫预编译,表示为正式的编译做准备,预编译也被称为预处理。

  • (1)**.c —————预处理(预编译)—————> **.i

    如果编译过程是一次性完成的话,.i文件只是一个过渡性文件,.i被称为扩展后的c源码文件。

    为什么还叫c源码文件呢?

    因为预处理后,只是宏定义等东西不见了,但是C源码依然还在,比如main函数,各种自己写的子函数,依然存在,所以还是被称为c源码文件。打开.i文件后,我们是能够看的懂的,所以.i文件是ascii文件。后面会演示给大家看。

  • (2)预编译是以单个文件为单位来进行的

      a.c ——————> a.i

      b.c ——————> b.i

      当然**.i的这个名字并不是固定的。

  • (3)预处理做了什么处理

    • 1)宏替换

      将宏替换为真实的宏体, 比如程序性中有使用NUM这个宏,这个宏的定义为#define NUM 100,程序中所有的NUM都会被替换为100。
    • 2)包含头文件

      将include包含的.h头文件内容,全部复制到.c文件中,因为头文件中定义了类型、宏、函数声明等等,

      这些都是函数调用会用到的,你调用某个函数时,就必须包含这个函数要的头文件。

      疑问:头文件那么多内容,都包含进去的话,不会太多了吗?

      编译时,编译器只使用要用的东西,用完后包含的内容都会被丢弃,实际上并不占空间。
    • 3)条件编译

      处理#if #endif 这类的东西
    • 4)处理一些特殊的预处理关键字

      有关预处理的宏定义、头文件包含、条件编译、特殊预处理关键字,会在后面专门的《预处理》章节中讲到。

第2步:编译

  • (1)***.i ———编译———> ***.s

    .s:汇编文件

  • (2)同样也是以单个文件为单位来进行的

  • (3)编译做了什么

    将c语法的c源码,翻译为汇编语法的汇编源码。

  • (4).s是ascii码文件

    因为汇编也是人能看懂的文字编码形式,所以.s汇编文件也是ASCII码文件。

第3步:汇编

  • (1)***.s ————汇编————> ***.o

    .o文件是纯二进制文件

    因为.o中放的是纯二进制的机器指令,所以我们打开后看不懂。

  • (2)同样也是以文件为单位来进行的

  • (3)汇编做什么

    将ASCII的汇编源码,翻译为能够被CPU执行的机器指令,.o文件中放的就是机器指令。

    但是.o文件还无法运行,需要链接后才能运行。

第4步:链接

***1.o ——————————\<br/>
          \<br/>
***2.o ____________\ a.out(可执行文件)<br/>
           /<br/>
....		  /<br/>
          /<br/>
***n.o —————————/<br/>
  • (1)链接(连接)做了什么

    • 1)将众多的.o合成一个完整的可执行文件

      .o之间相互依赖的,比如a.o中调用的函数,被定义在了b.o中,如果不链接在一起的话,是无法工作的。
    • 2)链接时,需要加入额外的启动代码

      这个启动代码并不是我们自己写的,main函数是由启动代码调用的,我们的程序是从启动代码开始运行的,后面会介绍启动代码是怎么来的。
    • 3)链接为一个可执行文件时,需要进行符号解析和地址重定位

      后面会介绍什么事符号解析和地址重定位。
  • (2)Linux下可执行文件命名问题

    在windows下,可执行的尾缀时.exe,但是在Linux下,可执行文件没有固定的尾缀。

  • (3)如果整个C工程就一个.c,最后得到的只有一个.o,此时还需要链接吗,可不可以直接执行呢?

    同样的要链接后才能运行,因为链接后才有启动代码和重定位后的地址,否者无法运行。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

空無一悟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值