深入理解 C 语言程序的编译与链接过程

Android BLE扫描指南:解决设备发现问题 假设你正在开发一个MAUI应用,用于扫描并连接到BLE设备。你的代码在Windows上运行得很好,但在Android上却无法发现任何设备。尽管你已经在中声明了必要的权限,并且在运行时请求这些权限,扫描还是无法工作。 阅读详情

在 C 语言的世界里,我们编写的源代码最终如何变成能在计算机上运行的程序?这背后离不开编译和链接的神奇魔法。今天,我们就来详细拆解这个过程,带你一探究竟。

一、程序的两种环境

ANSI C 标准定义了 C 语言实现的两种关键环境:

  • 翻译环境:负责将我们编写的源代码转换为计算机可执行的机器指令(二进制指令)。
  • 执行环境:用于实际运行生成的可执行程序,输出最终结果。

简单来说,翻译环境就像一位 "翻译官",把人类能看懂的 C 语言代码翻译成机器能理解的二进制语言;而执行环境则像一个 "舞台",让翻译后的程序在上面 "表演"。

二、翻译环境的工作流程

翻译环境的工作可分为编译和链接两大过程,其中编译又细分为预处理、编译和汇编三个步骤。对于一个包含多个源文件(如 test1.c、test2.c、test3.c)的项目,其处理流程如下:

  1. 每个.c 文件单独经过编译器处理,生成对应的目标文件
  2. 所有目标文件和链接库经过链接器处理,最终生成可执行程序

不同系统下的目标文件后缀

  • Windows 环境:.obj
  • Linux 环境:.o

三、编译的三个阶段

3.1 预处理(预编译)

预处理阶段会将源文件(.c)和头文件(.h)处理成以.i 为后缀的中间文件。在 gcc 环境下,可使用以下命令查看预处理结果:

gcc -E test.c -o test.i

预处理的主要工作包括:

  • 删除所有#define并展开所有宏定义
  • 处理条件编译指令(#if、#ifdef、#elif、#else、#endif)
  • 处理#include指令,将头文件内容插入到指令位置(该过程是递归的)
  • 删除所有注释
  • 添加行号和文件名标识,方便后续调试
  • 保留#pragma等编译器指令

预处理后的.i 文件已经展开了所有宏,插入了所有头文件内容,非常适合用来检查宏定义或头文件包含是否正确。

3.2 编译

编译阶段将预处理后的.i 文件通过词法分析、语法分析、语义分析及优化,生成汇编代码文件(.s)。在 gcc 中使用以下命令:

gcc -S test.i -o test.s

我们以array[index] = (index+4)*(2+6);为例,看看编译过程的具体操作:

  • 词法分析:将代码分割成一系列记号(关键字、标识符、字面量、特殊字符等),上述代码会被拆分为 16 个记号,如array(标识符)、[(左方括号)、index(标识符)等。
  • 语法分析:将记号组成语法树,表达代码的语法结构。
  • 语义分析:对语法树进行语义检查,如类型匹配等,并在语法树中添加类型信息。
  • 优化:对代码进行优化处理,生成更高效的汇编代码。

3.3 汇编

汇编阶段将汇编代码文件(.s)转换为机器可执行的指令,生成目标文件(.o 或.obj)。在 gcc 中使用以下命令:

gcc -c test.s -o test.o

汇编过程相对直接,每一条汇编语句几乎都对应一条机器指令,汇编器会根据汇编指令和机器指令的对照表进行一一翻译,不进行指令优化。 

四、链接

链接是将多个目标文件和链接库组合成可执行程序的过程,主要包括地址和空间分配、符号决议和重定位等步骤。

链接解决了多文件、多模块之间的相互调用问题。例如,在 test.c 中调用 add.c 中定义的函数或变量时:

  • 编译 test.c 时,编译器并不知道被调用函数或变量的实际地址,会暂时搁置
  • 链接阶段,链接器会查找这些符号的实际地址,并修正所有引用,这个过程称为 "重定位"

五、程序的运行环境

当可执行程序生成后,就进入了运行环境:

  1. 程序载入内存:通常由操作系统完成,独立环境中可能需要手工安排
  2. 开始执行:调用 main 函数作为程序入口
  3. 代码执行:
    • 使用运行时堆栈(stack)存储局部变量和返回地址
    • 使用静态(static)内存存储静态变量,其值在整个程序执行期间保持不变
  4. 程序终止:正常终止 main 函数,或意外终止

总结

C 语言程序从源代码到可执行程序的过程看似复杂,实则是一系列有序的转换:预处理处理宏和头文件,编译将代码转换为汇编语言,汇编生成机器指令,链接将多个模块组合成可执行程序。理解这个过程,有助于我们更好地调试和优化程序。

如果想深入了解更多细节,推荐阅读《程序员的自我修养》一书,它会带你探索目标文件格式、链接的底层实现等更深层次的知识。

YOLO模型在STM32微控制器上的部署:1.98M参数如何塞进嵌入式设备? <think>我们根据内容生成不超过150字的摘要。内容主要是关于YOLO模型在STM32微控制器上的部署,包括STM32N6 NPU、模型量化、工具链、开源方案和架构设计。摘要需要简洁概括主要点。 字数限制:≤150字。需要包含关键信息:STM32N6运行YOLO,困难,方案(NPU、INT8量化、工具链),性能(34 FPS 9.4mJ)。结尾可能提到开源和生态。 写中文摘要。注意不超过150字。</think>本文探讨YOLO模型在STM32微控制器上的部署。集成NPU的STM32N6搭配轻量化YOL 阅读详情

相关推荐

基于Matlab与Gurobi的园区微电网风光储协同规划:从独立运营到联合优化的建模实战

本文详细介绍了如何利用Matlab与Gurobi进行园区微电网的风光储协同规划建模实战。通过构建从独立运营到联合优化的数学模型,结合Yalmip工具箱,旨在解决源荷不匹配问题,实现储能系统的最优配置与运行,从而降低总供电成本并提升新能源利用率。

weixin_29053073的博客 140

【C语言】编译与链接:深入理解程序构建过程

本篇将深入理解程序构建过程,以便于我们在编写程序的过程同时,理解底层是如何从程序的创建到生成可执行程序的。

专注于 C/C++ 后端开发,涵盖基础语法、Linux系统与网络、MySQL数据库、常见算法及项目经验。 2593

智慧城市项目实战:如何将你的地理数据从城市坐标系(如上海2000)转换到国家CGCS2000?

本文详细介绍了智慧城市项目中地理数据坐标系转换的全流程解决方案,重点讲解如何将城市坐标系(如上海2000)转换到国家CGCS2000。通过七参数布尔莎模型、ArcGIS Pro、QGIS开源方案及Python编程实现,帮助实施团队解决坐标系不统一的技术难题,确保空间分析精度。

weixin_28725949的博客 307

“预编译、编译、汇编、链接”四个过程

C语言的编译链接过程要把我们编写的一个c程序(源代码)转换成可以在硬件上运行的程序(可执行代码),需要进行编译和链接。编译就是把文本形式源代码翻译为机器语言形式的目标文件的过程。链接是把目标文件、操作系统的启动代码和用到的库文件进行组织形成最终生成可执行代码的过程 从图上可以看到,整个代码的编译过程分为编译和链接两个过程,编译对应图中的大括号括起的部分,其余则为链接过程。 过程图解如下: 编...

lyw851230的专栏 1220

微磁模拟实战指南:从OOMMF安装到首个3D模型运行

本文详细介绍了OOMMF微磁模拟软件的安装与使用,从环境配置到首个3D模型运行的完整教程。涵盖Windows、Linux和macOS平台的安装避坑指南,以及MIF文件编写、并行计算优化等实战技巧,帮助研究人员快速掌握这一开源工具在磁畴壁运动、磁滞回线等微磁学问题中的应用。

weixin_29294597的博客 153

绕过卡巴斯基通过RPC控制lsass注入DLL

参考国外的XPN以及3gstudent大佬的文章: https://blog.youkuaiyun.com/xiangshen1990/article/details/104872566 https://gist.github.com/xpn/93f2b75bf086baf2c388b2ddd50fb5d0 原理:正常的ssp扩展(dll)可以加载到lsass进程中去,比如kerberos验证都是通...

2ed 3524

预处理、编译、汇编、链接

C语言的编译链接过程要把我们编写的一个c程序(源代码)转换成可以在硬件上运行的程序(可执行代码),需要进行编译和链接。编译就是把文本形式源代码翻译为机器语言形式的目标文件的过程。链接是把目标文件、操作系统的启动代码和用到的库文件进行组织形成最终生成可执行代码的过程 从图上可以看到,整个代码的编译过程分为编译和链接两个过程,编译对应图中的大括号括起的部分,其余则为链接过程。 过程图解如下: 编译过程又可以分成两个阶段:编译和汇编。 编译 编译是读取源程序(字符流),对之进行词法和语法的分析,将高级语言指令转

Chasing__Dreams的博客 2096

DAC60501与STM32的I2C通信实战:从寄存器配置到电压输出

本文详细介绍了如何使用STM32通过I2C通信驱动DAC60501数模转换器,实现精确的模拟电压输出。内容涵盖从硬件连接到软件模拟I2C驱动编写,再到DAC寄存器配置与电压计算的全流程实战指南,并提供了关键的驱动实例代码和常见问题调试技巧,帮助开发者快速掌握这一嵌入式开发中的实用技能。

weixin_29197835的博客 368

C语言编译过程详解

IDE的使用让很多和我一样的人对C/C++可执行程序的底层生成一知半解,不利于我们深入理解原理。在这里小结一下,望路过的大神指正~ 前言:从一个源文件(.c文件)到可执行程序到底经历了哪几步,我想很多人都知道,但是每一步具体做了什么,估计很多像我一样的人就不能说的清清楚楚,明明白白了。 C语言编译过程分成四个步骤: 1,由.c文件到.i文件,这个过程叫预处理 2,由.i文件到.s文件...

请叫我皮皮虾的博客 3359

反激开关电源设计全解析:从CCM/DCM原理到PCB布局实战

开关电源作为现代电子设备的能量转换核心,其核心原理是通过高频开关动作实现高效的电能变换。反激拓扑因其结构简单、成本低廉且易于实现电气隔离,成为小功率离线式电源的主流选择。其技术价值在于通过变压器耦合实现能量存储与传递,解决了安全隔离与多路输出等关键需求,广泛应用于充电器、适配器及家电供电等场景。本文聚焦反激电路,深入剖析其CCM与DCM两种工作模式的原理差异及选型考量,并结合伏秒平衡定律与RCD钳位等热词,详解从变压器计算到MOSFET选型的完整工程设计流程。

weixin_31951365的博客 344

OCR开发车架号识别vin码识别系统

一、vin码识别车架号识别系统简介   vin码识别车架号识别系统,结合VIN码主机厂数据库及自身多年文字识别经验,针对机动车配置参数等信息的查询及采集业务推出的一款VIN码自动识别产品。   车架号识别vin码识别,主要应用在智能手机IOS与Android两个平台中。前端扫描查询模式,无需联网,只需扫描汽车前挡风玻璃右下角的VIN玛(车架号),即可轻松识别出车辆产地、品牌、车

OCR13512721355的博客 1434

C语言之编译链接全过程分析

C语言的编译链接过程要把我们编写的一个c程序(源代码)转换成可以在硬件上运行的程序(可执行代码),需要进行编译和链接。编译就是把文本形式源代码翻译为机器语言形式的目标文件的过程。链接是把目标文件、操作系统的启动代码和用到的库文件进行组织,形成最终生成可执行代码的过程。过程图解如下: 从图上可以看到,整个代码的编译过程分为编译和链接两个过程,编译对应图中的大括号括起的部分,其余则为链接过程。

mcvsyy521的专栏 1750

TC3XX - MCAL知识点(三十七):AURIX™ TC3xx 的BootLoader烧录APP完成之后跳转使多个核均正常运行

摘要:针对AURIX TC3xx多核芯片在软件复位后仅Core0能启动的问题,分析发现该芯片在Cold Power-on Reset(断电复位)时会完整执行多核启动流程,而Application Reset(软件复位)会跳过从核初始化。解决方案包括:1)在BootLoader中显式调用IfxCpu_startCore()函数启动其他核;2)通过跳转函数强制各核从指定地址启动;3)双Boot场景下让每个核独立响应复位命令。实测表明,软件复位后需手动触发从核启动,或采用断电复位方式确保所有核正常初始化。

梦想技术家 412

c语言自定义头文件_c语言编译过程

这篇思考下C语言的编译过程,通过编译过程再看其它,也许会有不一样的理解。参与过程的结果,才会对结果有不一样的感觉。只追求结果,也许会得出“理所当然”的错觉,自己深陷其中,还浑然不觉。太多所谓的“客观”,到头来还只是个主观的理解,如此而已!学习c语言的第一节课,往往第一个接触的代码便是如图1所示的代码:#include int main(){ printf("hello world!...

weixin_39677538的博客 1224

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

C语言之程序环境、编译过程、宏与函数

一、程序编译过程 1.程序编译过程 组成一个程序的每个源文件通过编译过程分别转换成目标代码。 每个目标文件由链接器捆绑在一起。形成一个单一而完整的可执行程序。 链接器同时也会引入标准C函数库中任何被程序所用到的函数,而且它可以搜索程序库,将其需要的函数也链接到程序中。 2.编译过程 预处理,选项gcc -E test.c -o test.i预处理完成之后就停下来,预处理之后产生的结果都放...

Sheena997的博客 567

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

C语言编译过程总结

概述 C语言的编译链接过程要把我们编写的一个c程序(源代码)转换成可以在硬件上运行的程序(可执行代码),需要进行编译和链接。编译就是把文本形式源代码翻译为机器语言形式的目标文件的过程。链接是把目标文件、操作系统的启动代码和用到的库文件进行组织形成最终生成可执行代码的过程。过程图解如下: 从图上可以看到,整个代码的编译过程分为编译和链接两个过程,编译对应图中的大括号括起的部分,其余则为链接过程。 编译过程 编译过程又可以分成两个阶段:编译和汇编。 编译 编译是读取源程序(字符流),对之进行词法和语法的分析,

TBAALi的博客 294

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

程序编译过程分析

1.概述 一个C语言程序从源代码文件变成最后的可执行程序文件,需要经历预处理、编译、汇编、链接四个过程。 预处理:条件编译、头文件包含、宏替换,生成.i文件 编译:将预处理后的文件转换成汇编语言,生成.s文件 汇编:汇编变为目标代码(机器代码)生成.o文件 链接:链接目标代码,生成可执行程序。 日常使用GCC编译器完成上述过程,需要以下选项: -E P...

夜黯竹亭风的博客 762

c语言编译全过程各个阶段分析

C语言编译全过程 编译的概念:编译程序读取源程序(字符流),对之进行词法和语法的分析,将高级语言指令转换为功能等效的汇编代码,再由汇编程序转换为机器语言,并且按照操作系统对可执行文件格式的要求链接生成可执行程序。 编译的完整过程:C源程序-->预编译处理(.c)-->编译、优化程序(.s、.asm)-->汇编程序(.obj、.o、.a、.ko)-->链接程序(.exe、.elf、.ax

yt123456yt的专栏 902

C 语言编译过程总结详解

C 语言编译过程总结详解 从图上可以看到,整个代码的编译过程分为编译和链接两个过程,编译对应图中的大括号括起的部分,其余则为链接过程。 编译过程 编译过程又可以分成两个阶段:编译和会汇编。编译 编译是读取源程序(字符流),对之进行词法和语法的分析,将高级语言指令转换为功能等效的汇编代码,源文件的编译过程包含两 1 个主要阶段:第一个阶段

上善若水 1248

[转]C++编译链接过程详解

C语言的编译链接过程要把我们编写的一个c程序(源代码)转换成可以在硬件上运行的程序(可执行代码),需要进行编译和链接。编译就是把文本形式源代码翻译为机器语言形式的目标文件的过程。链接是把目标文件、操作系统的启动代码和用到的库文件进行组织,形成最终生成可执行代码的过程。过程图解如下: 从图上可以看到,整个代码的编译过程分为编译和链接两个过程,编译对应图中的大括号括起的部分,其余则为链接过程...

Stephen___Qin的博客 96

C语言编译全过程

C语言编译全过程     编译的概念:编译程序读取源程序(字符流),对之进行词法和语法的分析,将高级语言指令转换为功能等效的汇编代码,再由汇编程序转换为机器语言,并且按照操作系统对可执行文件格式的要求链接生成可执行程序。     编译的完整过程:C源程序-->预编译处理(.c)-->编译、优化程序(.s、.asm)-->汇编程序(.obj、.o、.a、.ko)-->链接程序(.exe、

静-静的雪 568

C语言入门学习——源文件的编译运行具体过程

本文介绍了C语言程序的编译执行过程。首先区分了编译型语言(C/C++)、解释型语言(Python)和混合型语言(Java)的特点。重点讲解了编译型语言的编译过程:预处理→编译为汇编代码→翻译为机器码→链接库文件生成可执行文件。文中还介绍了GCC、Clang等主流编译器,以及汇编语言作为底层语言的作用。通过类比说明编译器将源代码转换为二进制可执行文件的过程,帮助读者理解程序从编写到运行的完整流程。

2501_93553916的博客 727

C语音的预处理,编译,汇编,链接过程分析

C语音的预处理,编译,汇编,链接过程分析 1.C程序编译分为以下几步: 预处理 (生成 .i文件) 编译(生成 .s文件) 汇编(生成 .o文件) 链接(生成 .exe文件) 2.通过图解来理解编译过程 3.通过Linux的gcc编译C文件,并逐步分析: vim test.c //Linux指令 //test.c只写一个简单的hello world #include<stdi...

qq_43203949的博客 2314

可运行的C语言程序的拓展名,可运行的c语言程序的扩展名为什么?

可运行的c语言程序的扩展名为“.exe”。c语言程序经过“编译程序”编译之后,生成一个后缀为“.obj”的二进制文件;然后由“连接程序”,把此“.obj”文件与c语言提供的各种库函数连接在一起,生成一个后缀“.exe”的可执行文件。教程推荐:《c语言教程视频》C语言源程序经过C语言编译程序编译之后,生成一个后缀为“.OBJ”的二进制文件(称为目标文件),最后还要由称为“连接程序”(Link)的软件...

weixin_35843035的博客 4413

C 语言的编译与链接

在 C 语言编程的世界里,编译和链接是将我们编写的源代码转换为可执行程序的重要过程。理解这两个步骤对于编写高效、可靠的 C 语言程序至关重要。

Q741_147的博客 456

C的编译和链接

c语言中存在一些预定义符号__FILE__//进⾏编译的源⽂件__LINE__//⽂件当前的⾏号__DATE__//⽂件被编译的⽇期__TIME__//⽂件被编译的时间__STDC__//如果编译器遵循ANSI C,其值为1,否则未定义#define 机制是C/C++预处理器中的一个重要功能,它允许开发者定义宏(macro)来实现文本替换。

2302_81146716的博客 1095
上一篇: 深入理解 C 语言指针:从基础到高级应用
下一篇: C 语言文件操作入门:从基础到实战
THGML
博客等级 码龄3年 49粉丝 21原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值