C/C++的编译链接——深入浅出

        一个C/C++程序要想从源代码变为可执行文件,经过了哪些过程呢?大体分为编译链接

在编译阶段需要编译环境的支持:GCC,Cl等等,在运行阶段需要执行环境的支持,Windows,LInux等等

步骤

在他们细节处,又会有许多的步骤,编译阶段分为三个步骤:预处理,汇编,编译;在链接阶段分为一个阶段,就是链接

 

 

先让我们来看一下两个源程序文件,也是后面实验的基础

Add.c

test.c

预处理

        (文本操作):生成 .i 文件

gcc xxx.c -E -o xxx.i 在预处理阶段停下来,生成预处理文件

1、包含头文件,#include ——预处理指令

2、define 宏定义符号的替换;

3、注释删除

gcc Add.c -E -o Add.i生成了一个.i文件

 gcc test.c -E -o test.i

        可以看到test.c文件的内容发生了很多的变化,1、#include <stdio.h>不见了;2、上方多了一堆我们没有写进去的函数。这是怎么回事呢?

        可以看到头文件时被替换了,那我们去打开这个文件来看一下,看看里面是何方神圣,如此轻松就将头文件的内容替换了。

 可以看到上面几行内容出现在了test.i文件里面,这就是包含头文件

那么我们把这两张图片进行以下对比可以发现,test.i里面的内容有很多空行,那些内容要么是条件,要么是注释语句,但是宏定义语句还没有出现,接下来我们一起看下一段的宏定义是如何进行的:

 可以看到定义了两个宏常量,那么在预处理之后会产生怎样的反应呢?

可以看到宏常量的定义被删除了,main函数的域里面,A,B则是直接被替换成了宏常量的值

        到这里,我们知道了,在预处理的时候,编译系统首先会包含头文件,然后将宏进行一个替换,并且删除一些条件编译的语句以及删除注释

编译

        生成  .s  文件

gcc xxx.i -S        在预处理结束后,在此基础上在编译阶段停下来,生成.s汇编文件

​        把c语言代码翻译成汇编代码

​        1、语法分析

​        2、词法分析

​        3、语义分析

​        4、符号汇总,只汇总全局的变量,不会汇总局部变量

这里我们就直接一次性展开代码执行结果

可以看到,在编译阶段生成了一堆我们不认识的代码,这是汇编代码,这里我们主要关注符号汇总,符号汇总,是把全局变量形成一张表,每个变量对应着一个地址,可以抽象成下图:

 这里之所以把Add的地址设置成0x000,不是因为他是在第一个,根本原因是在test.c文件中,使用了extern修饰,也就是说这里只是一个声明,函数有没有没有关系,当需要用到的时候就会去查找符号表,如果符号表里面有该函数,那么则会与该函数产生链接,从而调用该函数。

汇编

生成 .o 二进制目标文件

gcc xxx.s -c 在编译阶段结束后,在此基础上在汇编阶段停下来,生成.o文件

把汇编指令翻译成二进制指令,人类看不懂,这是机器读得懂的,这种文件的格式是elf

每个.o文件都会形成符号表,readelf xxx.o -s可以查看符号表

链接:生成可执行文件

1、合并段表

2、符号表的合并和重定位

这里我们也是一次性将命令执行

 

可以看到全都是一堆乱码,因为在链接的时候生成的是一个二进制文件,这不是给人们读的,而是机器来读的,但是有一个命令可以读取这种文件,感兴趣的伙伴们可以直接点击readelf进行更为详细的了解。

接下来我们看一下符号表是什么? 

 可以看到test.o的符号表有两个全局变量,Add.c的符号表里面有一个全局变量

 总结

        从源程序到目标程序一个经历4大阶段,预处理/预编译,编译,汇编,链接,在预处理的时候会包含头文件,删除注释,宏定义替换,条件编译;在编译的时候则会形成汇编文件,在这一阶段会进行语法,词法,语义的分析以及符号汇总;在汇编阶段则生成二进制代码,同时生成一张用于全局函数/变量的地址定位的符号表,最终形成可执行文件。

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值