首页 > 编程语言 >程序的编译与链接(C语言为例) #代码写好后到运行期间要经过怎样的过程呢?# 粗略版 #

程序的编译与链接(C语言为例) #代码写好后到运行期间要经过怎样的过程呢?# 粗略版 #

时间:2023-06-06 23:32:59浏览次数:44  
标签:符号表 为例 代码 程序 C语言 编译 test 链接

(编译与链接)


前言

每当我们运行一段代码时,编译器都会自动的帮我们编译代码并将代码转换为一个二进制可执行文件(.exe), 有了这个可执行文件,便可以执行我们写的程序了。那么编译器对代码的编译以及生成可执行程序的过程是怎样的呢?这个问题便是本文章将要探讨的。


程序的环境

ANSI C的任何一种实现中,存在两个不同的环境,一种是==翻译环境==,一种是==执行环境==:

  • 翻译环境:在这个环境中源代码被转换为可执行的机器指令;
  • 执行环境:这个环境用于实际执行代码。

补充:

在这里插入图片描述

程序的编译与链接

首先看看 ==翻译环境== 的简图: 在这里插入图片描述

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

编译本身也分为几个阶段: ==预编译 —> 编译 —> 汇编==

在这里插入图片描述

  • <font size=5>预编译(预处理)</font> 预编译又叫预处理。预编译不是编译,而是编译前的处理,编译器正式开始编译程序之前,会执行一段预处理程序(又称预处理器)专门对程序执行预处理操作。

预处理阶段要做的事情主要是这些:

  1. #include 头文件的包含;
  2. #define定义符号的替换和删除;
  3. 注释的删除。

接下来在linux中用==gcc==编译器对一段代码进行预处理,如下:

在这里插入图片描述 预处理过后,我们观察test.i这个预编译后的文件:

<font color=blue size=5>指令:gcc -E test.c -o test.i</font>

在这里插入图片描述

可以看到,代码一下子膨胀了许多,这正是因为头文件被包含进来了,当来原先的#define与注释也不见了。


  • <font size=5>编译</font>

编译阶段是将C语言代码翻译成==汇编代码==, 其过程有:

  1. 语法分析;
  2. 词法分析;
  3. 语义分析;
  4. ==符号汇总==。

符号汇总就是将相关的函数,以及全局变量汇总:

例如以下代码汇总后客观图:

在这里插入图片描述 将上述代码编译后:

<font color=blue size=5>指令:gcc -S test.c -o test.s</font>

在这里插入图片描述

可以看到,C语言被翻译成了汇编代码。


  • <font size=5>汇编</font>
  1. **汇编是将汇编代码翻译成了==二进制指令==(存放目标文件),也就是生成目标文件的一步(test.o)**;
  2. 汇编使汇总的符号==形成符号表==,也就是每个符号对应一个地址。

如下: 在这里插入图片描述

就将上述代码汇编,我们来看看test.o是不是二进制文件呢?

<font color=blue size=5>指令:gcc -c test.c -o test.o</font>

在这里插入图片描述

可以看到,的确是一些二进制乱码。


通过编译的一系列过程后,接下来就是链接了

<font color=blue size=5>链接的相关过程有:</font> <font size=4> 1. 合并段表(这里不解释,需了解细读《程序员的自我修养》这本书,里面对整个编译链接部分都有很详细的讲解) 2. 符号表的合并和重定位。

<font color=red>这里只讲解符号表的合并:

  1. 在上面所探讨的编译过程,每一个文件都会形成自己的目标文件,在汇编这一步,又会形成自己的符号表;
  2. 如果一个程序有两个文件,就会有两个符号表,所以,符号表的合并,就是链接的一步。

例如test1.c文件和test2.c文件的符号表合并过程:

在这里插入图片描述

最终,通过链接器和链接库将各个目标文件链接后形成可执行文件。


<font color=blue size=5>程序执行的过程:

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

写在最后

如果说,你对这一块特别感兴趣,想继续深入,你可以读<font color=red size=4>《程序员的自我修养》</font>这本书,这本书里对这一块的知识有很详细的解析。

感谢阅读本小白的博客,错误的地方请严厉指出噢!

标签:符号表,为例,代码,程序,C语言,编译,test,链接
From: https://blog.51cto.com/u_16019252/6428797

相关文章

  • 逍遥自在学C语言 | break-循环的中断与跳转
    前言在C语言中,break语句是一种控制流语句,它用于终止当前所在的循环结构(for、while、do-while)或者switch语句,从而跳出循环或者结束switch语句的执行。一、人物简介第一位闪亮登场,有请今后会一直教我们C语言的老师——自在。第二位上场的是和我们一起学习的小白程序猿—......
  • C语言编程语法—文件读写
    一个文件,无论它是文本文件还是二进制文件,都是代表了一系列的字节。C语言不仅提供了访问顶层的函数,也提供了底层(OS)调用来处理存储设备上的文件。本章将讲解文件管理的重要调用。打开文件您可以使用fopen()函数来创建一个新的文件或者打开一个已有的文件,这个调用会初始化类型FIL......
  • 关于C语言题602
    1、编写函数voidcount(chara[],charw[][10],intn,intb[])。功能是:统计w指向的数组中的n个单词在a指向的字符串中各自出现的次数(将非字母字符看作单词分割符),拧将统计结果依次保存在b指向的数组中。 #include<stdio.h>#include<string.h>#defineN10intmain(){......
  • [linux]记录一次C语言综合练习
    题目根据特定功能设计程序,要求由main.c,Fun1.c-Fun3.c选择其中任意两个,共三个C语言文件和1个头文件组成,其中fun1.c,fun2.c和fun3.c都使用了define.h中的声明,C语言文件的功能分别是:fun1.c:输出9*9口诀fun2.c:有1、2、3、4个数字,能组成多少个互不相同且无重复数字的三位数?......
  • 统信UOS系统开发笔记(三):从Qt源码编译安装之编译安装Qt5.12.8
    前言  上一篇,是使用Qt提供的安装包安装的,有些场景需要使用到自己编译的Qt,所以本篇如何在统信UOS系统上编译Qt5.12.8源码。<br>统信UOS系统版本  系统版本:  Qt源码下载  参考博文《获取下载Qt安装包,Qt源码全国网址备忘录(不用注册Qt账户,即可下载各版本Qt安装包和Qt源......
  • CENTOS 6.0 mini系统编译安装mysql 5.5.16过程
     下面的安装过程是www.centos.bz博主朱海茂的文章,在此一并谢过,看到你的这篇文章我编译成功了,谢谢。根据我的情况进行了简单的修改,请见谅。我的是centos6的系统,使用mini的安装模式,安装完成后的第一件事要配置好网络,这个过程就郁闷了我好几次,mini模式安装出来没有setup,网络只能......
  • java反编译工具jd-gui和插件jd-eclipse,还有插件Enhanced Class Decompiler 3.3.0
    JD-GUI和JD-ECLIPSE可以直接在下面的网址进行下载http://java-decompiler.github.io/ (1)注意:JD-GUI.exe单机版有很多版本,有些旧版本反编译出来的源码和高版本反编译出来的源码是区别的1.低版本的反编译可能和实际源码有出入2.1.6.6版本反编译的源码中有中文无法正常复制? ......
  • 第一章 初识C语言-第一节(C语言固定程序;全局变量和局部变量)
    c语言主函数固定程序#include<stdio.h>intmain(){return0;}全局变量和和局部变量全局变量定义在程序块前,局部变量定义在程序块中。intnum1=0; //num1是全局变量,其使用域可在整个程序块intmain(){{intnum2=2; //num2是局部变量,其使用于域在当前程序块}printf("%d\n",,num2);......
  • VsCode配置Wdk7600开发环境 以及 "自动编译" 和 sources文件简单介绍..
    目录VsCode配置Wdk7600开发环境以及"自动编译"和sources文件简单介绍..一丶简介1.2软件安装1.3开发环境配置步骤1.4集成终端编译1.4.1集成任务1.4.2设置为全局任务.二丶Sources文件编程2.1INCLUDES字段2.2i386_SOURCES32位驱动使用内联汇编2.3AMD64_SOURCES使用......
  • Centos7 离线编译安装python3
    一,安装依赖yum-yinstallzlib-develbzip2-developenssl-develncurses-develreadline-develtk-develgccmake安装libffi-devel依赖yuminstalllibffi-devel-y注意:如果不安装这个包,python3可以装成功,但是后面装flask、uwsgi等依赖python3中有个内置模块叫ctype......