程序的编译

雨轩(小宇) 雨轩(小宇)     2022-12-12     797

关键词:

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

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

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

2、详解编译+链接

2.1 编译环境

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

2.2 编译的几个阶段

预编译->编译->汇编

接下来用Linux解释这几个阶段

  1. 先通过命令vim test.c 创建test.c文件

    这是test.c的内容
  2. 通过命令 gcc test.c -E 进行预处理
    通过预处理我们可以看到写的c文件内容在下面,上面有一段内容是来自stdio头文件的,我们可以stdio.h发现是来自 /usr/include/ 路径下的。
  3. 我们重新创建test.c文件
  4. 通过 gcc test.c -E > test.i 进行预编译并将预处理后的文件放于文件test.i中。

通过下面的图我们发现预编译进行了三部分的处理

  • 完成了头文件的包含#include
  • #define定义的符号和宏的替换
  • 删除了注释
  1. 在通过命令 gcc test.i -S 将C代码编译成汇编代码生成文件 test.s
    这里汇编就不作解释了,看得懂的都是大佬(狗头保命

编译阶段进行了四个步骤:

  • 语法分析
    源代码程序进入扫描器(scanner),将源代码的字符序列分割成一系列的记号(Token)。并将记号进行分类,如符号表(存放标识符)和文字表(存放数字、字符串常量)等。
  • 词法分析
    语法分析器(Grammer Parser)对记号(Token)进行语法分析,并生成语法树(Syntax Tree)。
  • 语义分析
    语义分析器完成对表达式的语法层面的分析。它不知道语句真正含义,是对静态语义的分析。所谓静态语义,是编译期可确定的语义,包括声明、类型匹配和类型转换。对应的动态语义,则是运行期确定的语义。
  • 符号汇总
    源代码优化器对源代码进行优化。如将编译期可确定的值进行优化。
    此处四个步骤参考链接: gcc编译原理.
  1. 在通过命令 gcc test.s -c 将汇编代码翻译成二进制指令(机器指令)生成对应目标文件 test.o

    test.o 文件格式是 elf 格式,elf 文件又是分段组成的。
    这里我们可以通过命令 readelf test.o -s 来查看,可以看到符号汇总(红色圈圈部分),是我们刚刚在test.c文件中定义的。
  2. 最后通过命令 gcc test.o 可以将多个目标文件通过连接器与链接库进行链接生成a.out文件(可执行文件)。

链接作用:

  • 合并段表(elf格式文件相同段的部分进行合并,a.out也是elf格式文件)
  • 符号表合并和重定位
  1. 我们这里在重新创建两个文件 test.c 和 add.c


    我们再次通过命令 readelf test.o -s 来查看符号汇总


    通过红色部分,我们可以看到两个文件的符号汇总。
    变量和函数都是有地址的,但是不能两个一样的符号在一起把,extern外部声明的符号是没有实际地址的,所以这里用的是sum.c文件中变量的地址。所以链接完之后,符号表合并的就是这些变量。

2.3 运行环境

程序执行的过程:

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

点个赞在走吧!!!

程序的编译

这里写目录标题1、程序的翻译环境和执行环境2、详解编译+链接2.1编译环境2.2编译的几个阶段2.3运行环境1、程序的翻译环境和执行环境在ANSIC的任何一种实现中,存在两个不同的环境。第1种是翻译环境,在这个环境中... 查看详情

程序的静态链接(代码片段)

程序的静态链接程序的产生程序是由程序员编写,经过编译链接过程,最终能够在计算机中运行的东西。本质上来说编译链接过程其实就是将由人能看懂的代码段翻译成机器能看懂的代码段,然后指导机器的运行,比起程序在机... 查看详情

可以编译使用 Pillow/PIL 的程序的 Python 编译器?

】可以编译使用Pillow/PIL的程序的Python编译器?【英文标题】:PythoncompilerthatcancompileaprogramthatutilisesPillow/PIL?【发布时间】:2017-01-3000:00:18【问题描述】:我编写了一个使用Pillow模块(PIL分支)的程序。我想将完成的程序编译为.ex... 查看详情

使用 -g gcc 标志编译的程序是不是比不使用 -g 编译的同一程序慢?

】使用-ggcc标志编译的程序是不是比不使用-g编译的同一程序慢?【英文标题】:Isaprogramcompiledwith-ggccflagslowerthanthesameprogramcompiledwithout-g?使用-ggcc标志编译的程序是否比不使用-g编译的同一程序慢?【发布时间】:2014-07-2919:17:09【... 查看详情

程序动态编译代码

c#可以在程序运行过程中动态的编译代码,并生成程序集加载在内存,然后就可以动态的调用代码生成的程序了,这有点像我们的vs编译器,感兴趣的可以制作属于自己的c#编译器:要实现这种功能,我们只需要调用CSharpCodeProvider... 查看详情

.class和.java区别

二者区别在于:java文件是源程序,class文件是编译后的代码。关于源程序未经编译的,按照一定的程序设计语言规范书写的,人类可读的文本文件。源程序可以是以书籍或磁带或其他载体的形式出现,但最为常用的格式是文本文... 查看详情

如何编译包内的两个程序?

】如何编译包内的两个程序?【英文标题】:HowtoCompilethetwoprocedureinsideofpackage?【发布时间】:2019-04-2810:42:09【问题描述】:我在包内创建了三个程序。现在要编译包里面仅有的两个程序。是否可能,如果是意味着如何?【问题... 查看详情

编译执行vs解释执行

一般编译程序从对源程序执行途径的角度不同,可分为解释执行和编译执行。所谓解释执行是借助于解释程序完成,即按源程序语句运行时的动态结构,直接逐句地边分析边翻译并执行。像自然语言翻译中的口译,随时进行翻译。所... 查看详情

源码怎么编译

...用编译器编译。编译(compilation,compile)功能:1、利用编译程序从源语言编写的源程序产生目标程序的过程。2、用编译程序产生目标程序的动作。编译就是把高级语言变成计算机可以识别的2进制语言,计算机只认识1和0,编译程序... 查看详情

是否允许 C++ 编译器发出编译同一程序的不同机器代码?

】是否允许C++编译器发出编译同一程序的不同机器代码?【英文标题】:IsaC++compilerallowedtoemitdifferentmachinecodecompilingthesameprogram?【发布时间】:2011-03-0411:48:38【问题描述】:考虑一种情况。我们有一些特定的C++编译器、一组特定... 查看详情

是否允许 C++ 编译器发出编译同一程序的不同机器代码?

】是否允许C++编译器发出编译同一程序的不同机器代码?【英文标题】:IsaC++compilerallowedtoemitdifferentmachinecodecompilingthesameprogram?【发布时间】:2011-03-0411:48:38【问题描述】:考虑一种情况。我们有一些特定的C++编译器、一组特定... 查看详情

编译原理

...译原理就是将高级语言通过编译器转换成低级语言,即源程序通过编译器转换成目标程序。2)学习编译原理的好处:1.可以让我们更好,更容易地理解程序语言。2.学习编译原理,能让我们通过多种途径地去培养我们写程序的思... 查看详情

c/c++程序编译过程详解

C语言的编译链接过程要把我们编写的一个c程序(源代码)转换成可以在硬件上运行的程序(可执行代码),需要进行编译和链接。编译就是把文本形式源代码翻译为机器语言形式的目标文件的过程。链接是把目标文件、操作系... 查看详情

c/c++程序编译过程详解

C语言的编译链接过程要把我们编写的一个c程序(源代码)转换成可以在硬件上运行的程序(可执行代码),需要进行编译和链接。编译就是把文本形式源代码翻译为机器语言形式的目标文件的过程。链接是把目标文件、操作系... 查看详情

我们的程序能否在编译时确定它在哪个编译器中编译? [复制]

】我们的程序能否在编译时确定它在哪个编译器中编译?[复制]【英文标题】:Canourprogramdeterminewhichcompileritisbeingcompiledin,atcompiletime?[duplicate]【发布时间】:2018-12-1611:02:53【问题描述】:存在多种用于C和C++的编译器,其中一些用... 查看详情

CMake传递的变量编译器无法编译简单的程序

】CMake传递的变量编译器无法编译简单的程序【英文标题】:CMakePassedvariablescompilerisnotabletocompileasimpleprogram【发布时间】:2017-07-2821:24:10【问题描述】:我正在尝试使用CMake交叉编译应用程序。当我对交叉编译器的路径进行硬编... 查看详情

简述将源程序编译成可执行程序的过程

一个源程序到一个可执行程序的过程:预编译、编译、汇编、链接。其中,编译是主要部分,其中又分为六个部分:词法分析、语法分析、语义分析、中间代码生成、目标代码生成和优化。预编译:主要处理源代码文件中的以“... 查看详情

1.gcc程序编译

...的代表作之一。gcc可以在多个硬件平台上编译出可执行的程序,其执行效率与一般的编译器相比,效率要高20%~30%。  GCC编译器能将C,C++语言源程序,汇编程序编译,链接成可以执行文件,在Linux系统中,可执行文件没有统一... 查看详情