当前位置: 首页 > news >正文

【C语言】编译与链接过程

文章目录

  • 一、程序的两种环境
  • 二、翻译环境
    • 2.1 多文件项目的构建流程
    • 2.2 编译的三个步骤
      • 2.2.1 预处理(预编译)
      • 2.2.2 编译
      • 2.2.3 汇编
    • 2.3 链接
  • 三、运行环境

一、程序的两种环境

在ANSI C的任何一种实现中,都存在两个不同的环境,它们共同支撑着C语言程序的生命周期。

  • 翻译环境:这是源代码被转换为可执行的机器指令(二进制指令)的地方。我们编写的.c源文件就是在这个环境中经历一系列处理,最终变成能被计算机识别的二进制代码。
  • 执行环境:顾名思义,它是用于实际执行代码的环境。当翻译环境生成可执行程序后,就会在执行环境中运行,产生我们需要的结果。

举个简单的例子,假设有test1.ctest2.ctest3.c三个源文件,它们会先在翻译环境中经过编译、链接等过程生成可执行程序,然后这个可执行程序在运行环境中输出结果。

二、翻译环境

翻译环境的核心任务是将源代码转换为可执行的机器指令,它由编译和链接两个大的过程组成,而编译又可以进一步分解为预处理(预编译)、编译、汇编三个步骤。

2.1 多文件项目的构建流程

一个C语言项目往往包含多个.c文件,这些文件共同协作才能完成特定的功能。那么,多个.c文件是如何一步步生成可执行程序的呢?

  • 多个.c文件会单独经过编译器的处理,生成对应的目标文件。这里需要注意的是,在Windows环境下,目标文件的后缀是.obj;而在Linux环境下,目标文件的后缀是.o
  • 这些多个目标文件和链接库一起经过链接器的处理,最终生成可执行程序。链接库指的是运行时库(支持程序运行的基本函数集合)或者第三方库。

比如,test.c经过编译器处理生成test.objadd.c经过编译器处理生成add.obj,然后这些.obj文件与链接库在链接器的作用下生成可执行程序。

  • Windows 环境下:
  • Linux环境下:

2.2 编译的三个步骤

如果我们把编译器的工作展开,会得到更细致的三个过程:

2.2.1 预处理(预编译)

预处理阶段,源文件(.c为后缀)和头文件(.h为后缀)会被处理成为以.i为后缀的中间文件。

在gcc环境下,我们可以使用如下命令观察对test.c文件预处理后的.i文件:

gcc -E test.c -o test.i

预处理阶段主要处理源文件中以#开始的预编译指令,具体规则如下:

  • 将所有的#define删除,并展开所有的宏定义。
  • 处理所有的条件编译指令,如#if#ifdef#elif#else#endif
  • 处理#include预编译指令,将包含的头文件的内容插入到该预编译指令的位置。这个过程是递归进行的,也就是说被包含的头文件也可能包含其他文件。
  • 删除所有的注释。
  • 添加行号和文件名标识,方便后续编译器生成调试信息等。
  • 保留所有的#pragma的编译器指令,供编译器后续使用。

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

2.2.2 编译

编译过程是将预处理后的.i文件进行一系列的词法分析、语法分析、语义分析及优化,最终生成相应的汇编代码文件(.s为后缀)。

在gcc环境下,编译过程的命令如下:

gcc -S test.i -o test.s

我们以一段简单的代码array[index] = (index+4)*(2+6);为例,来看看编译过程具体做了什么。

  • 词法分析:源代码程序被输入扫描器,扫描器会把代码中的字符分割成一系列的记号,这些记号包括关键字、标识符、字面量、特殊字符等。上面的程序经过词法分析后,会得到16个记号,比如array(标识符)、[(左方括号)、index(标识符)、](右方括号)、=(赋值)等。
  • 语法分析:语法分析器会对扫描产生的记号进行语法分析,从而产生语法树。这些语法树是以表达式为节点的树。对于上面的代码,会生成以赋值表达式为根节点,下标表达式和乘法表达式为子节点的语法树,下标表达式又包含array标识符和index标识符,乘法表达式则由两个加法表达式组成等。

  • 语义分析:语义分析器完成语义分析,即对表达式的语法层面进行分析。编译器所能做的是语义的静态分析,通常包括声明和类型的匹配、类型的转换等。这个阶段会报告错误的语法信息。比如在上面的代码中,会对每个标识符和表达式进行类型标识,确认array是整型数组,index是整型,各个表达式的结果也是整型等。

经过这些步骤后,就会生成汇编代码文件。

2.2.3 汇编

汇编器的作用是将汇编代码(.s为后缀)转变为机器可执行的指令(目标文件,.o.obj为后缀)。每一个汇编语句几乎都对应一条机器指令,汇编过程就是根据汇编指令和机器指令的对照表一一进行翻译,不做指令优化。

在gcc环境下,汇编的命令如下:

gcc -c test.s -o test.o

2.3 链接

链接是一个复杂的过程,它需要把多个目标文件和链接库链接在一起,最终生成可执行程序。链接过程主要包括地址和空间分配、符号决议和重定位等步骤,其解决的是一个项目中多文件、多模块之间互相调用的问题。

我们以一个具体的例子来理解链接的作用。假设有test.cadd.c两个.c文件:

test.c中的代码如下:

#include<stdio.h>// 声明外部函数externintAdd(intx,inty);// 声明外部的全局变量externintg_val;intmain(){inta=10;intb=20;intsum=Add(a,b);printf("%d\n",sum);printf("g_val=%d\n",g_val);return0;}

add.c中的代码如下:

intg_val=2022;intAdd(intx,inty){returnx+y;}

我们知道,每个源文件都会单独经过编译器处理生成对应的目标文件,即test.c生成test.oadd.c生成add.o。在test.c中,我们使用了add.c中的Add函数和g_val变量。

但在编译器编译test.c的时候,它并不知道Add函数和g_val变量的地址,所以会暂时把调用Add的指令的目标地址和g_val的地址搁置。直到最后链接的时候,链接器会根据引用的符号Add在其他模块(这里就是add.o)中查找Add函数的地址,然后将test.c中所有引用到Add的指令重新修正,让它们的目标地址为真正的Add函数的地址,对于全局变量g_val也是用类似的方法来修正地址。这个地址修正的过程就被叫做重定位。

三、运行环境

当可执行程序生成后,就会进入运行环境执行。程序的运行过程大致如下:

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

相关文章:

  • 2026同城寄大件物流排名 哪家省钱又靠谱 - 生活情报姬
  • 月之暗面发布2.8万亿参数开源大模型Kimi K3
  • 2026汉中哪家门窗口碑好!优选新标门窗 - 一个呆呆
  • SharePoint安装常见问题与解决方案全指南
  • 呼和浩特黄金回收全流程拆解:从进店检测到钱款到账,青城这五家店教你看门道 - 小城生活闲谈
  • Cursor响应式布局调试秘籍:3行代码定位viewport错位,15分钟修复跨设备渲染异常
  • 寄件省钱 2026年7月圆通快递怎么寄最便宜 全网5大寄件渠道深度评测 - 生活情报姬
  • 2026年7月快递省钱排行 寄便宜渠道推荐 - 生活情报姬
  • 5个步骤掌握FANBOX内容批量下载:告别手动保存的烦恼
  • 分布式多源歌词聚合系统:基于异步架构的高性能逐字歌词匹配引擎
  • 钻石回收收费规则科普|福州零杂费政策真伪辨别 - 大牌深度测评
  • STM32中断机制与库函数实现深度解析
  • 如何高效备份QQ空间历史记录:GetQzonehistory完整数据导出解决方案
  • 【数据结构】顺序表与通讯录的实现(C)
  • Claude 3.5 Sonnet技术解析:AI模型性能与Artifacts功能实战
  • 2026 合肥包河区奢侈品回收新标杆:易奢福全品类通收,从黄金名表到限量球鞋一站式变现 - 奢侈品回收实体店
  • AutoAttack日志分析:如何通过log_path追踪攻击过程与中间结果
  • 如何快速搭建个人音乐库:网易云音乐下载器的完整使用指南
  • 长沙名牌包包高价回收测评,2026 本地标杆门店易奢福 - 肉松卷
  • 重磅公示!2026年7月帝舵香港官方售後維修地址名錄,服務電話24小時在線 - 帝舵中国官方服务中心
  • CAN总线位定时配置:从原理到TMS320F2838x实战,解决通信不稳定问题
  • 终极APK安装指南:在Windows上轻松安装Android应用的完整解决方案
  • 告别Wand时间限制:用开源增强工具解锁完整专业功能
  • 2026青岛热玛吉机构实力大评比,青岛博士医美凭综合实力领跑本地抗衰榜单 - GrowUME
  • 部署实战:将DOTS-TTS-MLX-INT4集成到iOS/macOS应用的完整流程
  • LangChain 接入踩坑记:小团队别卷 Agent,先搞定权限隔离
  • 构建医疗信号处理流水线:WFDB Python库的5步实战应用
  • 平凡之路,因爱非凡:17 年乐味餐饮,做有温度的国民食堂 - GrowUME
  • 2026年亲测山东GEO优化公司推荐,到底哪家更靠谱专业? - GrowUME
  • 东莞靠谱的婚宴酒楼排行 - GrowUME