Linux编译器 gcc/g++ 的编译过程(程序的编译过程)

gcc是C语言对应的编译器,g++是C++对应的编译器。一段代码要转换成机器可以识别的形式,编译器是必不可少的;要让代码可以找到自己所需要的函数或者变量,这就需要链接器了,最终才生成我们看到的 可执行文件。这整个过程我们称为 “程序的编译过程” 。


目录

一、预处理

1、预处理的作用

2、 预处理指令

二、编译(生成汇编代码)

1、编译的作用

2、 编译指令

三、汇编(生成机器可识别代码)

1、汇编的作用

2、为什么不直接将c语言代码转化为二进制文件

3、  汇编指令

四、连接(生成可执行文件或库文件)

1、连接的作用

2、连接指令

五、gcc选项记忆


一、预处理

1、预处理的作用

预处理的主要功能是头文件包含、宏替换、条件编译、去除注释等,生成一个比较干净的C原始程序

  • 头文件展开:将#include 包含的头文件在目标文件展开
  • 宏替换:将定义的宏 替换为对应的值
  • 条件编译:遇到 #ifdefine 就进行条件判断,然后仅留下相应的结果,生成的文件中就不会包                    含#ifdefine等语句
  • 去除注释:既然要生成一个干净的C程序,注释是必然不需要的

2、 预处理指令

基本指令:gcc -E 依赖的.c文件  -o  输出的.i文件

#使用gcc编译器,编译的文件是add.c,执行到预处理就停止编译,生成的目标文件是add.i文件
gcc -E add.c -o add.i

-E:执行完预处理就停止编译过程

-o:目标文件,预处理生成的是 .i文件

二、编译(生成汇编代码)

1、编译的作用

这个阶段的主要任务是

  • 语法分析
  • 词法分析
  • 语义分析
  • 符号汇总(汇总的一般都是全局符号)

没有问题以后,将代码转化成汇编代码。

注意:这里汇总的目的是为后面两步在作准备。下一步的汇编阶段会生成符号表,链接阶段会合并符号表,实际程序在运行的时候,就会根据这个符号表去找对应的全局变量或者函数。至于为什么只汇总全局符号,因为全局内容可以被不同文件共享

2、 编译指令

基本指令:gcc  -S  依赖的.c文件  -o  生成的.s文件

                  gcc  -S  依赖的.i文件  -o  生成的.s文件

方式一:依赖.c文件。从头开始,经过预处理、编译,最后生成.s文件
gcc -S add.c -o add.s

方式二:依赖.i文件。使用上一次生成的文件,无需经过预处理,直接对上一次的文件进行编译
gcc -S add.i -o add.s

  -S:执行完编译就停止

-o:生成的目标文件是 .s 文件

三、汇编(生成机器可识别代码)

1、汇编的作用

汇编的作用主要有两点:

  • 生成符号表。我们在调用其他源文件中的函数时,比如Add函数,实际上就是根据最后合并的符号表中的地址来找到对应的函数。一个源文件就对应一个符号表。
  • 计算机无法识别汇编语言,需要生成计算机可识别代码(也就是二进制文件)

2、为什么不直接将c语言代码转化为二进制文件

第一个原因,早期写代码都是用的汇编语言,后来有了C语言,就有了现在的流程,C语言 ——》汇编语言 ——》二进制文件,分别对应着我们目前的三个阶段预处理 ——》 编译 ——》 汇编

第二个原因,现在如果要将c语言直接转化为 二进制文件,就相当于要放弃现有的编译器,成本太高。

3、  汇编指令

基本指令:gcc  -c  依赖的.c文件  -o  生成的.o文件

                  gcc  -c  依赖的.s文件  -o  生成的.o文件

(注意这里的-c 是小写的!!)

方式一:依赖.c文件。从头开始,经过预处理、编译、汇编,最后生成.o文件
gcc -c add.c -o add.o

方式二:依赖.s文件。使用上一次生成的文件,无需经过预处理、编译,直接对上一次的文件进行汇编操作
gcc -c add.s -o add.o

-c:执行完汇编就停下来

-o:生成的目标文件是 .o文件

四、链接(生成可执行文件或库文件)

1、链接的作用

首先会把上面不同源文件的 符号表合并;其次开始解读代码,若要用到xx第三方函数,就会根据路径连接到对应的库。在该阶段,Windows环境连接的是 .lib 文件来访问第三方库;Linux 环境连接的是 .so 文件来访问第三方库。

这一步会将生成的 .o文件转化为 可执行文件(Windows下的.exe文件)

2、连接指令

基本指令:gcc   依赖的.o文件  -o  生成的可执行文件

                  gcc   -o  生成的可执行文件  依赖的.c文件列表

方式一:从头开始,一直运行到最后生成可执行文件
gcc -o add add.c

方式二:在上一次add.o的基础上运行
gcc add.o -o add

这里就一直运行到结束了,无需停下来了

-o:生成的目标文件是可执行文件

五、整体过程

整体过程可以参考下图:

  1. 将源文件通过预处理、编译、汇编转换成目标文件(xxx.o文件)
  2. 目标文件由链接器(linker)捆绑在一起,同时从链接库中引入该程序所需要用到的函数(可以是标准C函数库、自定义链接库),最终形成一个单一而完整的可执行程序。

注意:不同环境下,链接和运行过程链接第三方库的方式可能不一样

  • Windows环境下
    • 链接阶段 —— 连接.lib 文件
    • 运行阶段 —— 连接 .dll 文件
  • Linux 环境下,无论是链接过程还是运行过程,用的都是 .so 文件。

 六、gcc选项记忆

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值