首页 > 其他分享 >编译和链接

编译和链接

时间:2024-04-03 13:00:59浏览次数:20  
标签:文件 int 编译 main 标识符 链接

一个软件的开发,一行代码的实现,实际上是由两个环节所构成的:翻译以及运行。
而这两个环节是在两个环境下所进行的:翻译环境和运行环境。
翻译环境负责将源代码转换为可执行的机器指令,也就是计算机能听懂的语言。
运行环境负责实际执行代码的操作。
翻译环境可以被分为两个部分:编译和链接。
而编译又可以被分为三个环节:预处理(预编译)、编译、汇编。
所以整个过程实际上也可以看成是四个环节。

编译
1.预处理(.c文件)
预处理部分顾名思义就是对编译过程进行一个预先的准备工作,预处理后的文件被称为中间文件。它的任务主要包括这几个方面。
(1)头文件包含
预编译会处理源代码中的#include指令,将指定的头文件内容插入到源文件中。这样可以将不同文件中的函数声明、宏定义等内容整合到一个文件中,方便编译器进行后续处理。
(2)宏替换
针对#define定义符号,宏名称,会将其替换为对应的宏定义内容,以达到简化代码编写,提高代码可读性和维护性的目的。
经过预处理后的.i⽂件中不再包含宏定义,因为宏已经被展开。并且包含的头⽂件都被插⼊到.i⽂件 中。所以当我们⽆法知道宏定义或者头⽂件是否包含正确的时候,可以查看预处理后的.i⽂件来确认。
(3)处理条件编译
#开头的指令就是预处理指令,根据条件来判断例如#ifdef、#ifndef、#if等是否编译特定部分的代码。
(4)其他的预处理操作
预处理阶段是为了接下来的编译和汇编过程有一个良好的操作环境而准备的,它能保证后续过程顺利进行。
2.编译
编译会将预处理后的中间文件转换为汇编代码,编译器会进行词法分析、语法分析、语义分析等操作来生成相应的中间表示形式,通常是汇编代码。(.s文件)
(1)词法分析
举例:下面这行代码:

int main() {
    int a = 10;
    int b = 20;
    int sum = a + b;
    return 0;
}

编译器会对其词法进行分析:

标记序列:
1. 标识符(int)
2. 标识符(main)
3. 左括号(()
4. 右括号())
5. 左大括号({)
6. 标识符(int)
7. 标识符(a)
8. 赋值运算符(=)
9. 常量(10)
10. 分号(;)
11. 标识符(int)
12. 标识符(b)
13. 赋值运算符(=)
14. 常量(20)
15. 分号(;)
16. 标识符(int)
17. 标识符(sum)
18. 赋值运算符(=)
19. 标识符(a)
20. 加号(+)
21. 标识符(b)
22. 分号(;)
23. 标识符(return)
24. 常量(0)
25. 分号(;)
26. 右大括号(})

源代码中的字符序列将被转换为标记序列,而这些标记序列将会在接下来的语法分析中起到作用。
(2)语法分析
语法树的概念:语法树以表达式为节点,这些节点之间带有一定的逻辑关系:

程序
├─ 声明列表
│  ├─ 声明:int a = 10;
│  ├─ 声明:int b = 20;
│  └─ 声明:int sum = a + b;
└─ 语句列表
   ├─ 赋值语句:a = 10;
   ├─ 赋值语句:b = 20;
   ├─ 赋值语句:sum = a + b;
   └─ 返回语句:return 0;

(3)语义分析
再编译过程中,语义分析会对语法分析生成的语法树进行语义检查,以确保源代码的语义是合法的。
针对给定的C语言代码段,可以进行如下的语义分析:

  • 变量a、b、sum的声明和使用是合法的。
  • 表达式sum = a + b; 中的操作数类型匹配,因为a和b都是整数类型。
  • 返回语句return 0; 中的返回值类型与main函数声明的返回类型int匹配。

3.汇编(.o文件(目标文件))
在进行完编译之后,合法的源代码就会进行汇编器进行语言的转换,会将高级语言的代码转换机器代码,也就是二进制指令。
链接
链接过程可以这样理解:链,指的是多个不同的文件;接,指的是将多个文件接在一起,从而生成可执行程序。链接解决的是一个项目中多文件多模块之间互相调用的问题。
其主要功能包括以下几个方面:
(1) 符号解析:在链接阶段,链接器会解析目标文件中的符号(如变量名、函数名等),并将其与其定义所在的目标文件或库文件进行关联。这样可以确保在程序中引用的符号能够正确地找到其定义,从而避免未定义符号或重复定义符号的错误。

(2)符号重定位: 在链接过程中,链接器会根据目标文件中的重定位信息,将各个目标文件中的代码段和数据段进行合并,并调整各个符号在内存中的地址。这样可以确保程序正确地访问和执行各个模块之间的代码和数据。
我们现在有两个源文件:

// main.c
extern int global_var;

int main() {
    global_var = 10;
    return 0;
}

// helper.c
int global_var;

首先编译时会生成两个目标文件main.o以及helper.o;
链接器会通过符号表来解析和重定位这些符号。在这个例子中,链接器会找到 main.o 中对 global_var 的引用,并将其关联到 helper.o 中 global_var 的定义上。同时,链接器会调整 main.o 和 helper.o 中 global_var 的地址,以确保它们在内存中的位置是正确的。
最终,链接器会将 main.o 和 helper.o 合并为一个可执行文件,并确保 main 函数能够正确地访问和修改 global_var 的值。这样,程序就能够在运行时正常执行,并正确地处理全局变量 global_var。

(3)库文件链接:链接器还会将程序所依赖的库文件链接到可执行文件中。这些库文件包括系统提供的标准库、第三方库或用户自定义库,用于提供各种功能和服务。链接器会将程序中引用的库函数的地址解析并链接到程序中,使得程序能够调用这些库函数。

(4)生成可执行文件:最终,链接器会将各个目标文件和库文件中的代码段和数据段合并,生成一个完整的可执行文件。这个可执行文件包含了程序的所有代码和数据,可以在计算机上直接执行,完成程序的功能。

总的来说,链接部分在编译过程中起着将各个模块整合为一个完整可执行程序的重要作用。链接器将程序的各个部分正确地组合在一起,生成一个可以在计算机上运行的可执行文件。

标签:文件,int,编译,main,标识符,链接
From: https://blog.csdn.net/Skrrapper/article/details/137176209

相关文章

  • mathematical-expression(MAE)数学表达式 数学函数 解析编译库,有效的快速和简单易用的数
    数学表达式SwitchtoEnglishDocument介绍本框架是一种针对数学公式解析的有效工具,能够解析包含嵌套函数,包含函数,数列步长累加等数学公式,返回值是一个数值的结果对象,同时也可以进行比较运算的操作,再进行比较的时候,返回值是一个布尔值结果对象。PS请尽量使用1.3.1版......
  • 机器学习编译MLC
    陈天奇-《机器学习编译》课程主页:https://mlc.ai/summer22-zh课程笔记:https://mlc.ai/zh/机器学习编译概述1.1什么是机器学习编译机器学习编译(machinelearningcompilation,MLC)是指,将机器学习算法从开发阶段,通过变换和优化算法,使其变成部署状态。开发形式是指......
  • 在aarch64上编译,fstack: master分支:5b97230c858598a10e1b82c tag: v1.23, origin/mast
    F-Stack一个基于DPDK的开源和高性能网络框架 基于DPDK23.11需要做如下操作sed替换:sed-n'/DEV_RX_OFFLOAD_IPV4_CKSUM/p'drivers/net/macb/*sed-i's/ETH_/RTE_ETH_/g'*.csed-i's/DEV_/RTE_ETH_/g'*.c f-stack适配dpdk20.11sed-i's/RTE_MBUF_F_RX_I......
  • Eval-Expression.NET: 在运行时计算、编译和执行C代码和表达式。
    https://www.5axxw.com/wiki/content/8ahrg3 在运行时评估、编译和执行动态C代码和表达式从简单的C数学表达式。。。intresult=Eval.Execute<int>("X+Y",new{X=1,Y=2});要解析的复杂代码。intresult=Eval.Execute<int>(@"varlist=newList<int>(){1......
  • 【嵌入式智能产品开发实战】(十四)—— 政安晨:通过ARM-Linux掌握基本技能【链接静态库与
    目录链接静态库动态链接与地址无关的代码全局偏移表延迟绑定共享库政安晨的个人主页:政安晨欢迎 ......
  • 精彩解读:短链接应用全方位探究
    1.短链接的定义和原理短链接是一种将长网址转换为短网址的服务,通过简化网址长度,方便用户分享和传播链接。短链接服务通过将长网址映射到短标识符的方式,实现对原始网址的压缩和简化。用户在访问短链接时,系统会将短链接还原为原始长网址,实现跳转到目标网页的功能。短链接的原......
  • Linux 编译升级内核
    要在CentOS上手动编译并安装Linux内核4.19.311,你需要遵循一系列步骤。以下是一个简化的流程概述,但请注意实际操作时需要根据你的CentOS版本、内核源码以及实际情况稍作调整:准备工作:登录到具有足够权限的用户(最好是root或使用sudo)。更新系统:sudoyumupdate-y安装编译......
  • windows下编译paho.mqtt
    1、准备(1)Github仓库地址:https://github.com/eclipse/paho.mqtt.chttps://github.com/eclipse/paho.mqtt.cpp(2)VisualStudio2022以及CMakehttps://visualstudio.microsoft.com/zh-hans/vs/community/https://cmake.org/download/2、编译C库首先clone源码到本地文件......
  • Linux研究(6):Linux 硬链接和软连接-详解
    导言:当涉及到Linux文件系统中的链接时,有两种常见类型:硬链接(HardLink)和软链接(SymbolicLink,也称为符号链接或软连接)。它们用于在文件之间创建关联,提供了一些非常有用的功能。下面是对硬链接和软链接的详细解释以及一个实验样例。1.硬链接(HardLink)硬链接是通过文件系统......
  • 【QT+QGIS跨平台编译】054:【exiv2lib+Qt跨平台编译】(一套代码、一套框架,跨平台编译)
    点击查看专栏目录文章目录一、exiv2lib介绍二、文件下载三、文件分析四、pro文件五、编译实践一、exiv2lib介绍  exiv2lib是一个用于处理图像元数据的开源C++库。它可用于读取、编辑和写入图像文件中的Exif元数据(ExchangeableImageFileFormat,可交......