【C语言】编译与链接过程
文章目录一、程序的两种环境二、翻译环境2.1 多文件项目的构建流程2.2 编译的三个步骤2.2.1 预处理预编译2.2.2 编译2.2.3 汇编2.3 链接三、运行环境一、程序的两种环境在ANSI C的任何一种实现中都存在两个不同的环境它们共同支撑着C语言程序的生命周期。翻译环境这是源代码被转换为可执行的机器指令二进制指令的地方。我们编写的.c源文件就是在这个环境中经历一系列处理最终变成能被计算机识别的二进制代码。执行环境顾名思义它是用于实际执行代码的环境。当翻译环境生成可执行程序后就会在执行环境中运行产生我们需要的结果。举个简单的例子假设有test1.c、test2.c、test3.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] (index4)*(26);为例来看看编译过程具体做了什么。词法分析源代码程序被输入扫描器扫描器会把代码中的字符分割成一系列的记号这些记号包括关键字、标识符、字面量、特殊字符等。上面的程序经过词法分析后会得到16个记号比如array标识符、[左方括号、index标识符、]右方括号、赋值等。语法分析语法分析器会对扫描产生的记号进行语法分析从而产生语法树。这些语法树是以表达式为节点的树。对于上面的代码会生成以赋值表达式为根节点下标表达式和乘法表达式为子节点的语法树下标表达式又包含array标识符和index标识符乘法表达式则由两个加法表达式组成等。语义分析语义分析器完成语义分析即对表达式的语法层面进行分析。编译器所能做的是语义的静态分析通常包括声明和类型的匹配、类型的转换等。这个阶段会报告错误的语法信息。比如在上面的代码中会对每个标识符和表达式进行类型标识确认array是整型数组index是整型各个表达式的结果也是整型等。经过这些步骤后就会生成汇编代码文件。2.2.3 汇编汇编器的作用是将汇编代码.s为后缀转变为机器可执行的指令目标文件.o或.obj为后缀。每一个汇编语句几乎都对应一条机器指令汇编过程就是根据汇编指令和机器指令的对照表一一进行翻译不做指令优化。在gcc环境下汇编的命令如下gcc -c test.s -o test.o2.3 链接链接是一个复杂的过程它需要把多个目标文件和链接库链接在一起最终生成可执行程序。链接过程主要包括地址和空间分配、符号决议和重定位等步骤其解决的是一个项目中多文件、多模块之间互相调用的问题。我们以一个具体的例子来理解链接的作用。假设有test.c和add.c两个.c文件test.c中的代码如下#includestdio.h// 声明外部函数externintAdd(intx,inty);// 声明外部的全局变量externintg_val;intmain(){inta10;intb20;intsumAdd(a,b);printf(%d\n,sum);printf(g_val%d\n,g_val);return0;}add.c中的代码如下intg_val2022;intAdd(intx,inty){returnxy;}我们知道每个源文件都会单独经过编译器处理生成对应的目标文件即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也是用类似的方法来修正地址。这个地址修正的过程就被叫做重定位。三、运行环境当可执行程序生成后就会进入运行环境执行。程序的运行过程大致如下程序载入内存在有操作系统的环境中一般由操作系统完成程序的载入在独立的环境中程序的载入必须由手工安排也可能是通过可执行代码置入只读内存来完成。开始执行程序程序执行便开始接着会调用main函数。执行程序代码此时程序将使用一个运行时堆栈stack存储函数的局部变量和返回地址。同时程序也可以使用静态static内存存储于静态内存中的变量在程序的整个执行过程中一直保留它们的值。程序终止程序可能正常终止于main函数也可能意外终止。

相关新闻

windows错误解决方案大全(不定期更新)

windows错误解决方案大全(不定期更新)

一、0x8007007ewindows更新错误winr→downlevel→回车→确认大多数文件修改日期(比如我的是2024/4/1 15:22)→移出/删除修改日期不是上述日期(2024/4/1 15:22)的→安装更新

2026/7/19 19:06:18 阅读更多 →
浏览器里同时跑 99 个 AI 和 2100+ 粒子:WebGL2、Canvas 与固定时间步优化实战

浏览器里同时跑 99 个 AI 和 2100+ 粒子:WebGL2、Canvas 与固定时间步优化实战

我在做《星团大作战》时,遇到的性能问题并不是"Canvas 能不能画几个圆",而是下面这些工作会同时出现: 1 名玩家和 99 个 AI 持续移动、追击、逃跑、分裂与吞噬;76007600 的世界里,基础食物对象有 2100 个&a…

2026/7/19 19:05:17 阅读更多 →
终极指南:Photoshop图层批量导出插件如何将工作效率提升5倍

终极指南:Photoshop图层批量导出插件如何将工作效率提升5倍

终极指南:Photoshop图层批量导出插件如何将工作效率提升5倍 【免费下载链接】Photoshop-Export-Layers-to-Files-Fast This script allows you to export your layers as individual files at a speed much faster than the built-in script from Adobe. 项目地址…

2026/7/19 19:05:17 阅读更多 →

最新新闻

Godot 4.3 2D游戏开发全流程:从零到发布的实战指南

Godot 4.3 2D游戏开发全流程:从零到发布的实战指南

1. 项目概述:为什么选择Godot 4.3作为2D游戏开发的起点? 如果你正在寻找一个能让你从零开始,亲手打造出一款完整2D游戏的引擎,并且希望这个过程足够清晰、可控,那么Godot 4.3绝对是一个值得你投入时间的选项。我之所以…

2026/7/21 0:00:19 阅读更多 →
HarmonyOS超级终端与服务卡片开发实战指南

HarmonyOS超级终端与服务卡片开发实战指南

1. HarmonyOS超级终端与服务卡片开发概述在鸿蒙生态中,超级终端(Super Device)和服务卡片(Service Widget)是构建无缝多设备体验的两大核心技术支柱。作为一名长期从事跨平台开发的工程师,我发现这两项技术…

2026/7/21 0:00:19 阅读更多 →
UE5 GAS框架下RPG被动技能系统:从核心原理到实战实现

UE5 GAS框架下RPG被动技能系统:从核心原理到实战实现

1. 项目概述:UE5 GAS RPG被动技能的核心价值在UE5里用GAS(Gameplay Ability System)做RPG游戏,主动技能像是你手里的武器,按一下打一下,逻辑直接,反馈也快。但被动技能,它更像是你身…

2026/7/21 0:00:19 阅读更多 →
GPMC接口设计:异步/同步模式与多路复用配置实战

GPMC接口设计:异步/同步模式与多路复用配置实战

1. GPMC接口设计:从硬件连接到软件配置的全局视角在嵌入式系统开发中,尤其是基于TI Sitara系列如AM263x这类高性能微控制器的项目里,外部存储器的扩展几乎是绕不开的一环。无论是存放大量非易失性代码的NOR Flash,还是作为高速数据…

2026/7/21 0:00:19 阅读更多 →
Octane Render与C4D汉化版安装与优化指南

Octane Render与C4D汉化版安装与优化指南

1. Octane Render与C4D的黄金组合:为什么选择这个方案?在三维创作领域,渲染器的选择往往决定了作品的最终呈现质量和工作效率。作为Cinema 4D(C4D)用户,Octane Render的GPU加速特性与实时预览功能&#xff…

2026/7/21 0:00:19 阅读更多 →
GO_并发编程---channel

GO_并发编程---channel

前置回顾Go 并发核心设计理念:不要通过共享内存来通信,而要通过通信来共享内存goroutine 之间数据同步、数据交互统一依靠 channel 实现,解决多协程资源竞争问题。一、Channel 基础概念作用实现多个 goroutine 同步协程之间安全共享、传递数据…

2026/7/20 23:59:18 阅读更多 →

日新闻

Octane Render与C4D汉化版安装与优化指南

Octane Render与C4D汉化版安装与优化指南

1. Octane Render与C4D的黄金组合:为什么选择这个方案?在三维创作领域,渲染器的选择往往决定了作品的最终呈现质量和工作效率。作为Cinema 4D(C4D)用户,Octane Render的GPU加速特性与实时预览功能&#xff…

2026/7/21 0:00:19 阅读更多 →
GPMC接口设计:异步/同步模式与多路复用配置实战

GPMC接口设计:异步/同步模式与多路复用配置实战

1. GPMC接口设计:从硬件连接到软件配置的全局视角在嵌入式系统开发中,尤其是基于TI Sitara系列如AM263x这类高性能微控制器的项目里,外部存储器的扩展几乎是绕不开的一环。无论是存放大量非易失性代码的NOR Flash,还是作为高速数据…

2026/7/21 0:00:19 阅读更多 →
UE5 GAS框架下RPG被动技能系统:从核心原理到实战实现

UE5 GAS框架下RPG被动技能系统:从核心原理到实战实现

1. 项目概述:UE5 GAS RPG被动技能的核心价值在UE5里用GAS(Gameplay Ability System)做RPG游戏,主动技能像是你手里的武器,按一下打一下,逻辑直接,反馈也快。但被动技能,它更像是你身…

2026/7/21 0:00:19 阅读更多 →

周新闻

Go语言静态资源打包方案对比与实践指南

Go语言静态资源打包方案对比与实践指南

1. 项目背景与核心需求在Go语言开发中,我们经常需要处理静态资源文件的打包问题。无论是Web应用的模板文件、前端资源,还是配置文件、证书等,都需要随程序一起分发。传统做法是将这些文件与编译后的二进制文件放在同一目录下,但这…

2026/7/20 5:57:49 阅读更多 →
Go语言实现高性能LDAP认证服务的架构与实践

Go语言实现高性能LDAP认证服务的架构与实践

1. 项目背景与核心价值LDAP(轻量级目录访问协议)作为企业级身份认证的黄金标准,已经服务了超过80%的财富500强公司。我在金融科技领域实施统一认证体系时,发现传统Java方案存在启动慢、内存占用高等痛点。而Go语言凭借其协程并发模…

2026/7/20 4:31:26 阅读更多 →
【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

更多请点击: https://intelliparadigm.com 第一章:AI面试官实战指南的核心价值与适用场景 AI面试官并非替代人类HR的“黑箱工具”,而是以可解释、可审计、可迭代的方式,赋能招聘全链路的关键基础设施。其核心价值在于将主观经验沉…

2026/7/20 5:56:42 阅读更多 →

月新闻