C语言程序编译与链接(拓宽视野的不二之选)

文章目录

  • 翻译环境和运行环境
    • 翻译环境
    • 预处理
    • 编译
    • 汇编
    • 链接
  • 运行环境

翻译环境和运行环境

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

第1种是翻译环境,在这个环境中源代码被转换为可执⾏的机器指					令(⼆进制指令)。
第2种是执⾏环境,它⽤于实际执⾏代码。

在这里插入图片描述

翻译环境

那翻译环境是怎么将源代码转换为可执⾏的机器指令的呢?这⾥我们就得展开开讲解⼀下翻译环境所做的事情。

其实翻译环境是由编译和链接两个⼤的过程组成的,⽽编译⼜可以分解成:预处理(有些书也叫预编译)、编译、汇编三个过程。

在这里插入图片描述

⼀个C语⾔的项⽬中可能有多个 .c ⽂件⼀起构建,那多个 .c ⽂件如何⽣成可执⾏程序呢?

  • 多个.c⽂件单独经过编译器,编译处理⽣成对应的⽬标⽂件。
  • 注:在Windows环境下的⽬标⽂件的后缀是 .obj ,Linux环境下⽬标⽂件的后缀是 .o
  • 多个⽬标⽂件和链接库⼀起经过链接器处理⽣成最终的可执⾏程序。
  • 链接库是指运⾏时库(它是⽀持程序运⾏的基本函数集合)或者第三⽅库。

在这里插入图片描述

预处理

在C语言中,预处理阶段是编译过程中的第一步,主要是通过预处理器对源代码进行处理,包括宏替换、头文件包含、条件编译等操作。下面详细解释一下预处理阶段的几个重要概念和操作:

  1. 头文件包含(Include Directives):
    #include 指令:用于包含其他文件的内容,分为尖括号包含系统头文件(如#include <stdio.h>)和双引号包含用户定义的头文件(如#include “myheader.h”)。

  2. 宏替换(Macro Replacement):
    宏定义:使用#define指令定义一个宏,如#define PI 3.14159。
    宏替换:预处理器会在编译前将代码中出现的宏名称替换为对应的值,比如将代码中的PI替换为3.14159。

  3. 条件编译(Conditional Compilation):
    条件编译指令:如#if、#ifdef、#ifndef、#elif、#else、#endif等,用于根据条件选择性地编译代码块。

  4. 其他预处理指令
    #undef:取消已定义的宏。
    #ifdef 和 #ifndef:判断某个宏是否已经定义。
    #error:在预处理时生成一个错误信息。
    #pragma:向编译器发出特定指令。

预处理器工作流程
1,将源文件中的头文件包含进来。
2,对源文件进行宏替换。
3,处理条件编译指令,根据条件编译部分代码。
4,生成一个经过预处理的中间文件,后缀为.i,供后续编译阶段使用。
5,删除所有的注释
6, 添加⾏号和⽂件名标识,⽅便后续编译器⽣成调试信息等

经过预处理后的.i⽂件中不再包含宏定义,因为宏已经被展开。并且包含的头⽂件都被插⼊到.i⽂件
中。所以当我们无法知道宏定义或者头⽂件是否包含正确的时候,可以查看预处理后的.i⽂件来确认。

编译

  1. 词法分析(Lexical Analysis):
    目的
    将源代码按照词法规则分割成单词(Token)序列。

    工作内容
    识别关键字、标识符、常量、运算符等单词,并生成对应的标记(Token)。生成标记流(Token Stream)作为下一步的输入。
    请添加图片描述

  2. 语法分析(Syntax Analysis):
    目的:
    将标记流转换成抽象语法树(Abstract Syntax Tree,AST)或语法分析树。

    工作内容:
    根据语法规则检查标记流是否符合语言语法规范。
    构建抽象语法树,表示源代码的结构和语法。

请添加图片描述

  1. 语义分析(Semantic Analysis):
    目的:
    进行语义检查,确保程序的语义正确。

    工作内容:
    检查类型匹配、变量的定义和使用是否正确。
    解析表达式,计算常量表达式的值。
    检查函数调用、返回值等语义正确性。

在这里插入图片描述

  1. 中间代码生成(Intermediate Code Generation):
    目的:
    将抽象语法树转换成中间代码表示。

    工作内容:
    生成一种中间表示形式,如三地址码、四元式等。
    将高级语言的结构转换成更加容易进行优化的形式。

  2. 优化(Optimization):
    目的:
    对中间代码进行优化,提高程序的执行效率。

    工作内容:
    利用各种优化技术,如常量传播、死代码删除、循环优化等,提高程序性能。
    生成更加高效的中间代码表示,以便后续的代码生成阶段使用。

  3. 代码生成(Code Generation):
    目的:
    将优化后的中间代码转换成目标机器代码。

    工作内容:
    根据目标机器的特性和指令集,将中间代码转换为机器指令。
    处理寄存器分配、指令选择等问题,生成最终的目标代码。

汇编

当将C语言代码转换为汇编语言时,主要涉及到编译器将高级语言代码翻译成等效的汇编语言代码。以下是详细介绍汇编语言的步骤:

  1. 指令表示
    汇编语言使用助记符(Mnemonics)来代表特定的机器指令,如mov用于数据传送、add用于加法运算等。
  2. 寄存器
    计算机有一组寄存器用于存储数据和执行操作,如通用寄存器(如eax、ebx)、数据寄存器(如edx)、地址寄存器(如esi、edi)等。
  3. 内存访问
    使用不同的寻址模式(如立即数偏移、寄存器间接寻址)来访问内存中的数据。
  4. 控制流
    汇编语言提供了跳转指令(如jmp)和条件跳转指令(如je、jne)来控制程序的执行流程。
  5. 过程调用
    使用call来调用函数,使用ret返回函数调用,需要处理函数参数传递和局部变量存储。
  6. 栈操作
    使用栈来保存函数调用过程中的返回地址、参数以及局部变量,通过push和pop指令来操作栈。
  7. 数据处理
    汇编语言提供了各种指令来进行数据处理,如移位指令、逻辑运算指令、算术运算指令等。
  8. 标志寄存器
    标志寄存器记录了运算结果的信息,如进位标志、零标志、符号标志等,影响程序的条件跳转。
    9.宏指令
    汇编语言支持宏定义,可以简化重复代码的书写,提高代码的可读性和维护性。

链接

链接是将多个目标文件(包括库文件)组合成一个可执行文件或动态链接库的过程。以下是链接过程的详细步骤:

  1. 符号解析(Symbol Resolution):
    目的:解析所有目标文件中的符号引用,确定它们对应的实际地址或存储位置。
    工作内容:
    遍历所有目标文件,收集每个符号(如函数名、全局变量名)的定义和引用信息。
    解析外部符号引用,确定这些符号最终在哪个目标文件或库文件中定义。
    2.重定位(Relocation):
    目的:修正目标文件中的相对地址,使其能正确地映射到最终的内存地址。
    工作内容:
    根据符号解析的结果,对所有涉及到的地址进行调整,确保它们能正确地指向符号的实际位置。
    生成包含所有修正地址的重定位表,以便在加载时进行修正。
  2. 地址空间分配(Address Allocation):
    目的:为目标文件中的变量和函数分配内存地址。
    工作内容:
    确定每个全局变量和函数在内存中的起始地址。
    处理重复定义和冲突,确保分配的地址不会发生重叠或冲突。
  3. 符号重命名(Symbol Renaming):
    目的:避免不同目标文件中的符号名字冲突。
    工作内容:
    对于静态链接,可以对不同目标文件中的相同符号进行重命名,以避免冲突。
    对于动态链接,通常使用全局符号表(Global Symbol Table)来管理符号名字,确保唯一性。
  4. 生成可执行文件或动态链接库(Executable/Dynamic Link Library Generation):
    目的:将经过符号解析、重定位等处理后的目标文件转换为最终的可执行文件或动态链接库。
    工作内容:
    将已经修改过的目标文件内容按照特定的格式组合成可执行文件或动态链接库。
    对于可执行文件,可能还需要添加一些运行时所需的信息,如程序入口点等。
  5. 符号表生成(Symbol Table Generation):
    目的:生成最终可执行文件或动态链接库中的符号表,记录符号名字和对应的地址信息。
    工作内容:
    生成包含所有符号信息的符号表,以便在加载时进行符号解析和重定位。

运行环境

1,程序必须载⼊内存中。在有操作系统的环境中:⼀般这个由操作系统完成。在独⽴的环境中,程序的载⼊必须由⼿⼯安排,也可能是通过可执⾏代码置⼊只读内存来完成。

2, 程序的执⾏便开始。接着便调⽤main函数。

3,开始执⾏程序代码。这个时候程序将使⽤⼀个运⾏时堆栈(stack),存储函数的局部变量和返回地址。程序同时也可以使⽤静态(static)内存,存储于静态内存中的变量在程序的整个执⾏过程⼀直保留他们的值。

4,终⽌程序。正常终⽌main函数;也有可能是意外终⽌。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/572465.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

高级数据结构与算法习题(5)

一、单选题 1、Which of the following binomial trees can represent a binomial queue of size 42? A.B0​ B1​ B2​ B3​ B4​ B5​ B.B1​ B3​ B5​ C.B1​ B5​ D.B2​ B4​ 解析:B。要表示一共含有42个节点的二项队列,我们不妨将42表示成为一个二进制形式:,…

iOS_convert point or rect 坐标和布局转换+判断

文章目录 1. 坐标转换2. 布局转换3. 包含、相交 如&#xff1a;有3个色块 let view1 UIView(frame: CGRect(x: 100.0, y: 100.0, width: 300.0, height: 300.0)) view1.backgroundColor UIColor.cyan self.view.addSubview(view1)let view2 UIView(frame: CGRect(x: 50.0, …

连接数据库(MySQL)的JDBC

目录 JDBC简介快速入门API详解DriverManager&#xff08;驱动管理类&#xff09;注册驱动&#xff1a;获取数据库连接(对象)&#xff1a; Connection&#xff08;数据库连接对象&#xff09;获取执行SQL的对象管理事务 Statement(执行SQL语句)执行DML、DDL语句执行DQL语句 Resu…

BaseDao封装JavaWeb的增删改查

目录 什么是BaseDao&#xff1f; 为什么需要BaseDao&#xff1f; BaseDao的实现逻辑 什么是BaseDao&#xff1f; Basedao 是一种基于数据访问对象&#xff08;Data Access Object&#xff09;模式的设计方法。它是一个用于处理数据库操作的基础类&#xff0c;负责封装数据库…

深度学习目标检测算法之RetinaNet算法

文章目录 前言RetinaNet 算法原理1.RetinaNet 简介2.backbone 部分3.FPN特征金字塔4.分类和预测5.Focal Loss 结束语 &#x1f482; 个人主页:风间琉璃&#x1f91f; 版权: 本文由【风间琉璃】原创、在CSDN首发、需要转载请联系博主&#x1f4ac; 如果文章对你有帮助、欢迎关注…

代码学习记录29----贪心算法

随想录日记part29 t i m e &#xff1a; time&#xff1a; time&#xff1a; 2024.03.27 主要内容&#xff1a;今天深入学习贪心算法&#xff0c;接下来是针对题目的讲解&#xff1a;1. 无重叠区间 2.划分字母区间 3. 合并区间 435. 无重叠区间763.划分字母区间56. 合并区间 T…

堆排序基础知识

堆排序基础知识 一、引言二、堆的基本概念三、堆排序的基本思想四、堆排序的详细过程五、堆排序的性能分析六、堆排序的应用七、堆排序的优缺点八、堆排序的实现技巧九、总结与展望 一、引言 堆排序是一种有效的排序算法&#xff0c;它的核心在于使用了一种称为“堆”的数据结…

计算机组成原理-6-计算机的运算方法

6. 计算机的运算方法 文章目录 6. 计算机的运算方法6.1 机器数的表示6.1.1 无符号数和有符号数6.1.2 有符号数-原码6.1.3 有符号数-补码6.1.4 有符号数-反码6.1.5 有符号数-移码6.1.6 原码、补码、反码的比较 6.2 数的定点表示和浮点表示6.2.1 定点表示6.2.2 浮点表示6.2.3 ΔI…

Day20:LeedCode 654.最大二叉树 617.合并二叉树 700.二叉搜索树中的搜索 98.验证二叉搜索树

654. 最大二叉树 给定一个不重复的整数数组 nums 。 最大二叉树 可以用下面的算法从 nums 递归地构建: 创建一个根节点&#xff0c;其值为 nums 中的最大值。递归地在最大值 左边 的 子数组前缀上 构建左子树。递归地在最大值 右边 的 子数组后缀上 构建右子树。 返回 nums …

Manacher算法学习笔记(洛谷题单 Part 5.3 Manacher)

0.随便说说 字符串学的太差了&#xff0c;每次字符串算法都是学完了就忘&#xff0c;正好上场 c f d i v 1 B cfdiv1B cfdiv1B考了一个 M a n a c h e r Manacher Manacher&#xff0c;就先复习它了。 1.一些概念 子串 ( s u b s t r i n g ) (substring) (substring)&#…

dump文件分析OOM及线程堆栈

OutOfMemoryError (OOM) 如果项目报错&#xff1a; OutOfMemoryError: Java heap space&#xff0c;说明堆内存空间&#xff08;Heap Space&#xff09;中没有足够的空间来分配对象了。 一旦发生 OOM&#xff0c;系统有可能不可用&#xff0c;或者频繁重启。属于非常严重的问题…

kubernetes负载均衡资源-Ingress

一、Ingress概念 1.1 Ingress概念 使用NodePort类型的Service可以将集群内部服务暴露给集群外部客广端,但使用这种类型Service存在如下几个问题。 1、一个端口只能一个服务使用,所有通过NodePort暴露的端口都需要提前规划;2、如果通过NodePort暴露端口过多,后期维护成本太…