C语言 程序的编译系统解析

 更新时间:2022年02月28日 16:54:58   作者:呆呆兽学编程  
编译程序的基本功能是把源程序(高级语言)翻译成目标程序。但是,作为一个具有实际应用价值的编译系统,除了基本功能之外,还应具备语法检查、调试措施、修改手段、覆盖处理、目标程序优化、不同语言合用以及人-机联系等重要功能

今天我来补一下C语言篇的程序的编译的一篇文章,也算是有一个结尾了。

程序的翻译环境和执行环境

在ANSI C的任何一种实现中,存在两个不同的环境 :

第1种是翻译环境,在这个环境中源代码被转换为可执行的机器指令。

第2种是执行环境 ,它用于实际执行代码。

一个.c的文件事如何变成.exe的可执行文件的呢?下面这张图片是一个大概的过程:

请添加图片描述

编译和链接

翻译环境

请添加图片描述

  • 组成一个程序的每个源文件通过编译过程分别转换成目标代码( object code )。
  • 每个目标文件由链接器( linker )捆绑在一 起,形成一个单一-而完整的可执行程序。
  • 链接器同时也会引入标准C函数库中任何被该程序所用到的函数,而且它可以搜索程序员个人的程序库,将其需要的函数也链接到程序中。

编译的几个阶段

接下来,我来用Linux平台来给大家演示一下编译的三个过程:

我们先编写一个简单C程序:

请添加图片描述

然后执行这样一句指令:

gcc test.c

这句指令是让gcc这个编译器来编译我们的代码,执行完这句指令我们会发现会生成一个a.out这样一个可执行文件,

请添加图片描述

我们执行再下面这样一句指令:

./a.out

这样我们就可以执行这个可执行文件了,

请添加图片描述

为了让大家更好地感受到编译的过程,我们来一步一步看:

预处理

我们执行再下面这样一句指令,让代码预处理完之后就停下来:

gcc -E test.c -o test.i

这句指令的意思就是把预处理完之后的信息输出到一个test.i的文件中。

请添加图片描述

可以发现的是,这里多了一个test,i的文件,我们可以打开看一看:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pGZW3x4b-1637932306122)(C:\Users\久别重逢还不错\AppData\Roaming\Typora\typora-user-images\image-20211126200920738.jpg)]

可以发现的是,有三个点发生了变化:

  • 头文件被展开
  • 宏被文本替换了
  • 注释被删除了

我们对原代码做一个处理,不包含stdio.h的头文件,我们自己写一个头文件:

再来看一下,预处理后的文件是什么样子的:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jICkxv4k-1637932306124)(C:\Users\久别重逢还不错\AppData\Roaming\Typora\typora-user-images\image-20211126201809726.jpg)]

效果通上面一样。

所以预处理的几个动作

  • 头文件的包含
  • 预处理指令的完成(eg:#define、#pragma…)
  • 注释的删除

编译

执行再下面这样一句指令让文件进行编译形成汇编代码:

gcc -S test.c

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nYnbbB65-1637932306125)(C:\Users\久别重逢还不错\AppData\Roaming\Typora\typora-user-images\image-20211126202540289.jpg)]

执行完之后就可以生产出一个test.s的文件,我们可以打开看一看:

这里其实就是汇编代码。

所以编译的几个动作

  • 语法分析
  • 词法分析
  • 语义分析
  • 符号汇总

符号汇总: 符号汇总的都是全局的符号。例如上面我们的代码头文件就汇总了一个Add,.c文件就汇总的一个Add和main。

汇编

接下来我们执行这样一条指令:

gcc -c test.c

对源文件进行汇编,结果生成了一个test.o的目标文件:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Segd6oKn-1637932306126)(C:\Users\久别重逢还不错\AppData\Roaming\Typora\typora-user-images\image-20211126203431140.jpg)]

打开这个文件,我们会发现这是一个我们看不懂的二进制文件:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YjEQb15l-1637932306127)(C:\Users\久别重逢还不错\AppData\Roaming\Typora\typora-user-images\image-20211126203517294.jpg)]

所以其实汇编是把汇编代码转换为二进制代码(机器指令)。

这个过程还做了一件件事——形成符号表

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-O6xmUQVU-1637932306127)(C:\Users\久别重逢还不错\AppData\Roaming\Typora\typora-user-images\image-20211126204552806.jpg)]

链接

链接做的两个事情

  • 合并段表
  • 符号表的合并和符号表的重定位

在Linux系统下,test.o二进制文件是用一个elf这样的格式来组织文件的。

elf会把文件组织成一个段。test.o和Add.o都有一个段,那么我们怎样才能看懂elf格式的文件呢?

我们有这样一个工具叫做readelf,他可以看懂这样一个文件,所以我们输入这样一条指令:

readelf test.o -a

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kDmpTiYe-1637932306128)(C:\Users\久别重逢还不错\AppData\Roaming\Typora\typora-user-images\image-20211126205639154.jpg)]

我们就确实可以看到这样一个段的存在。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xQnwleYa-1637932306128)(C:\Users\久别重逢还不错\AppData\Roaming\Typora\typora-user-images\image-20211126210149263.jpg)]

然后这下面还有符号表的汇总:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ufzQtz4Y-1637932306129)(C:\Users\久别重逢还不错\AppData\Roaming\Typora\typora-user-images\image-20211126210550360.jpg)]

其实a.out这个文件也是elf格式的,所以其实链接就是把这几个elf格式的文件的段表合并,然后test中的Add函数就有了地址。

运行环境

程序执行的过程:

  • 程序必须载入内存中。在有操作系统的环境中:一般这个由操作系统完成。在独立的环境中,程序的载入必须由手工安排,也可能是通过可执行代码置入只读内存来完成。
  • 程序的执行便开始。接着便调用main函数。
  • 开始执行程序代码。这个时候程序将使用一个运行时堆栈(stack),存储函数的局部变量和返回地址。程序同时也可以使用静态(static)内存,存储于静态内存中的变量在程序的整个执行过程一直保留他们的值。
  • 终止程序。正常终止main函数;也有可能是意外终止。

到此这篇关于C语言 程序的编译系统解析的文章就介绍到这了,更多相关C语言 程序编译内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C++实现主机字节序和网络字节序转换示例

    C++实现主机字节序和网络字节序转换示例

    这篇文章主要为大家介绍了C++实现主机字节序和网络字节序转换示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-11-11
  • 完美解决QT QGraphicsView提升到QChartView报错的问题

    完美解决QT QGraphicsView提升到QChartView报错的问题

    使用QT提供的QChartView来绘制图表,提升QGraphicsView控件继承QChartView后,然后将QGraphicsView提升到我们自己写的类,怎么才能确保提升后编译不报错呢,下面小编给大家带来了QT QGraphicsView 提升到QChartView报错解决方案,感兴趣的朋友一起看看吧
    2023-05-05
  • 在VC中隐藏控制台程序窗口的实现代码

    在VC中隐藏控制台程序窗口的实现代码

    大家都知道,当编写一个win32 console application时,当运行此类程序的时候默认情况下会有一个类似dos窗口的console窗口,但是有的时候我们只想在程序中运行一段功能代码,不希望显示这个console窗口,让代码执行完毕之后程序自动退出
    2013-04-04
  • C++版本基于ros将文件夹中的图像转换为bag包

    C++版本基于ros将文件夹中的图像转换为bag包

    这篇文章主要介绍了C++版本基于ros将文件夹中的图像转换为bag包,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-01-01
  • C++中关于union的使用方法说明

    C++中关于union的使用方法说明

    这篇文章主要介绍了C++中关于union的使用方法说明,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-11-11
  • C++ opencv实现几何图形绘制

    C++ opencv实现几何图形绘制

    这篇文章主要为大家介绍了C++ opencv实现几何图形的绘制示例实现代码,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-05-05
  • C++ List链表的介绍和使用

    C++ List链表的介绍和使用

    list是可以在常数范围内在任意位置进行插入和删除的序列式容器,并且该容器可以前后双向迭代,这篇文章主要介绍了C++ List链表的介绍和使用,需要的朋友可以参考下
    2023-03-03
  • C++派生类与基类的转换规则

    C++派生类与基类的转换规则

    基类与派生类对象之间有赋值兼容关系,由于派生类中包含从基类继承的成员,具体表现在以下几个方面,需要的朋友可以参考下
    2012-11-11
  • C语言函数栈帧解析

    C语言函数栈帧解析

    下面小编就为大家带来一篇浅谈C语言函数调用参数压栈的相关问题。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2021-09-09
  • VisualStudio 禁用移动文件到文件夹自动修改命名空间功能

    VisualStudio 禁用移动文件到文件夹自动修改命名空间功能

    这篇文章主要介绍了VisualStudio 禁用移动文件到文件夹自动修改命名空间功能,文章底部给大家介绍了解决安装VS2022时,出现未能安装包“Microsoft.VisualCpp.Redist.14,version=14.32.31332,chip”=x86,的问题及解决方法,需要的朋友可以参考下
    2022-09-09

最新评论