C语言之编译和链接

发布时间:2024年01月18日

目录

一、引言?

二、编译和链接

2.1 预处理(预编译)

2.2 编译

2.3 汇编

2.4 链接


一、引言?

#include <stdio.h>
int main()
{
    printf("hello, world\n");
    return 0;
}

像这样,只由ASCII字符构成的文件被称为文本文件,它需要经过翻译环境的编译和链接后才能成为二进制文件,也就是可执行程序。

可执行程序的内部是一系列二进制形式的计算机指令和数据的集合,CPU可以直接识别,但是对于程序员来说非常难以记忆和使用,所以程序员开发出了编程语言,使用这些语言来编写程序。

为了要运行环境中运行编写出来的程序,每条C语句都必须在翻译环境中被其他程序转化为一系列的汇编指令,然后这些指令按照格式打好包,并以二进制磁盘文件的形式存放起来。

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

  • 翻译环境,在这个环节中源代码被转换成可执行的机器指令
  • 执行环境,用于实际执行代码

翻译环境是由编译链接两个过程组成的,而编译又可以细分为预处理(预编译)、编译和汇编三个过程

二、编译和链接

在一个项目中可能同时存在多个.c文件,这些文件经过编译器处理编译出对应的目标文件,再和链接库一起经过链接器处理生成最终的可执行程序

2.1 预处理(预编译)

在预处理阶段,源文件和头文件会被处理成以 .i 为后缀的文件

我们用gcc编译器观察一下对 test.c 文件预处理后的 .i 文件,在终端输入以下指令:

gcc -E test.c -o test.i

预处理阶段主要处理源文件中以#为开头的预编译指令,例如#include,#define,处理的规则如下

(1)将所有的#define删除,并展开所有的宏定义

图中我们可以观察到,在 test.i 中#define指令已经被删除,M也被替换成了100

(2)处理所有的条件编译指令,如 #if ,#ifdef,#elif,#else,#endif

(3)处理 #include 预编译指令,将包含的头文件的内容插入到该预编译指令的位置。这个过程是递归进行的,也就是说被包含的头文件也可能包含其他头文件

(4)删除所有的注释

(5)添加行号和文件名标识,方便后续编译器生成调试信息等

(6)保留所有的 #pragma 编译器指令,因为后续编译器会用到

2.2 编译

编译器将预处理完的 .i 文本文件进行一系列的词法分析、语法分析、语义分析和优化,编译成以 .s 为后缀的汇编代码文件。汇编过程的命令如下:

gcc -S test.i -o test.s

汇编代码文件大概长这样:

假设有代码如下,编译过程该如何对其进行分析呢?

array [index] = (index+ 4 )*( 2 + 6 );

编译过程可分为6步:扫描(词法分析)、语法分析、语义分析、源代码优化、代码生成、目标代码优化。

(1)词法分析

将源代码程序输入扫描器中,扫描器将其中的字符序列分割成一系列的记号。上面的代码进行词法分析后得到了16个记号:

记号类型
array标识符
[左方括号
index标识符
]右方括号
=赋值
(左圆括号
index标识符
+加号
4数字
)右圆括号
*乘号
(左圆括号
2数字
+加号
6数字
)右圆括号

(2)语法分析

接下来,语法分析器将对扫描器生成的记号进行语法分析,产生语法树。

(3)语义分析

语义分析器对表达式进行语法层面分析。编译器所能做的分析是语义的静态分析。静态语义分析通常包括声明和类型的匹配,类型转换等。这个阶段会报告错误的语法信息

2.3 汇编

汇编器将汇编代码翻译成机器可执行的指令,每一条汇编语句几乎都对应一条机器指令。在这一步中,只是根据汇编指令和机器指令的对照表一一的进行翻译,不做指令优化

汇编会生成 .o 为后缀的目标文件,命令如下:

gcc -c test.s -o test.o

汇编后的目标文件就已经是二进制形式了,我们很难阅读

2.4 链接

目标文件在经过链接之后才能称为可执行文件。既然目标文件和可执行文件都是二进制格式,为什么还要再链接一次呢?

因为编译只是将我们自己写的代码变成了二进制格式,它还需要和标准库、动态链接库等结合起来,这些组件都是程序运行所必须的。

链接过程主要包括地址和空间分配,符号决议和重定位等步骤,解决的是一个项目中多文件、多模块之间互相调用的问题。

完.

文章来源:https://blog.csdn.net/Eristic0618/article/details/135681297
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。