编译与链接

前言

本人的技术笔记会优先发布在个人站点longyxblg.cn

翻译环境和运行环境

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

第一种是翻译环境,在这个环境中源代码被转换为可执行的机器指令

第二种是运行环境,用于实际执行代码

翻译环境

翻译环境是由编译和链接两大过程组成的

编译又可以分解成:预处理、编译、汇编三个过程

一个C语言项目中可能有多个.c文件构成,多个.c文件会单独经过编译器,编译处理生

成对应的目标文件,多个目标文件和链接库一起经过链接器处理生成最终的可执

行程序

在 windows 环境下目标文件后缀为.obj, linux 环境下目标文件后缀为.o

预处理

预处理阶段,源文件和头文件会被处理为.i文件

主要处理源文件中 # 开始的预编译指令

  • 将所有 #define 删除,并展开宏定义

  • 处理所有条件编译指令,如:#if、#ifdef、#elif、#else、#endif

  • 处理 #include 预编译指令,将包含的头文件的内容插入到该预编译指令的位置

  • 删除所有注释

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

  • 或保留所有的 #pragma 的编译器指令,编译器后续会使用

经过预处理后的.i文件中不再包含宏定义,因为宏已经被展开。并且包含的头文件

都被插入到.i文件

中。所以当我们无法知道宏定义或者头文件是否包含正确的时

候,可以查看预处理后的.i文件来确认。

编译

编译就是将预处理后的文件的进行词法分析、语法分析、语义分析及优化

假如有下列代码

c 复制代码
int arr[10] = { 0 };
arr[0] = 1;

词法分析

将源代码程序输入扫描器,扫描器的任务是简单的进行词法分析,将代码中的字符分割成一系列的记号(关键字、标识符、字面量、特殊字符等)

记号 类型
int 关键字
arr 标识符
[ 左方括号
10 数字
] 右方括号
= 赋值
{ 左大括号
0 数字
} 右大括号
arr 标识符
[ 左方括号
0 数字
] 右方括号
= 赋值
1 数字

语法分析

接下来语法分析器对扫描产生的记号进行语法分析从而产生语法树,这些语法树是以表达式为节点的数


语义分析

由语义分析器来完成语义分析,即对表达式的语法层次分析

编译器做的分析是语义的静态分析,通常包含声明和类型的匹配,类型的转换等,这

个阶段会报告错误的语法信息

汇编

汇编器是将汇编代码转转变成机器可执行的指令,每一个汇编语句几乎都对应一

条机器指令。就是根据汇编指令和机器指令的对照表一一的进行翻译,也不做指

令优化。

链接

链接是一个复杂的过程,需要把一堆文件链接在一起生成可执行程序

主要包括:地址和内存分配,符号决议和重定位等这些步骤

解决的是一个项目中多文件、多模块之间的调用问题

例如现在一个C语言项目中有两个文件 add.c 和 native_c.c

c 复制代码
// add.c
int num = 2026;
int Add(int x, int y)
{
return x+y;
}
c 复制代码
// native_c.c
#include <stdio.h>
//test.c
//声明外部函数
 
extern int Add(int x, int y);
//声明外部的全局变量
 
extern int num;

int main()
{
    int a = 10;
    int b = 20;
    int sum = Add(a, b);
    printf("%d\n", sum);
    return 0;
}

native_c.c 经过编译器处理生成 native_c.o

add.c 经过编译器处理生成 add.o

在 native_c.c 文件中使用了 add.c 中的 Add 函数

和 num 变量,必须知道 Add 函数 和 num 变量的地址,所以暂时会把调用 Add 的

指令的目标地址和 num 的地址搁置。等到链接的时候由链接器根据引用的符号

Add 在其他模块中查找 Add 的地址,然后将 native_c.c 所有引用 Add 的指令重新

修正,让他们的目标地址称为真正的 Add 函数的地址,变量 num 类似。这个地址修

正的过程称为重定位

相关推荐
个 人 练 习 生1 小时前
数据结构链表:带头双向循环链表
c语言·数据结构·经验分享·学习·其他·链表
智者知已应修善业17 小时前
【51单片机数码管逐位显示1-8余位不亮】2024-10-23
c语言·经验分享·笔记·嵌入式硬件·51单片机
caimouse18 小时前
ReactOS 图形系统分析(47):GDI 批处理 — gdibatch.c
c语言·开发语言
caimouse19 小时前
ReactOS 窗口系统分析(1):窗口对象与创建 — window.c
c语言·开发语言
caimouse20 小时前
ReactOS 图形系统分析(53):系统库存对象 — stockobj.c
c语言·开发语言·spring
caimouse21 小时前
ReactOS 图形系统分析(52):OpenGL 支持 — wingl.c
c语言·开发语言
j7~21 小时前
【C语言】《C语言函数递归完全指南:思想、限制、经典例题(阶乘/斐波那契/青蛙跳台阶/汉诺塔)与迭代优化》
c语言·函数递归·汉诺塔问题·青蛙跳台阶问题·递归与迭代·n的阶乘
YSL0701241 天前
动态内存管理
c语言
BreezeJuvenile1 天前
基于C语言的SPSC环形缓冲区程序实现
c语言·环形缓冲区