C语言:编译与链接

翻译环境和运行环境

在ANSI C的任何一种实现下,存在两种不同的环境:翻译环境和运行环境。

翻译环境:在该环境下,源代码被转换为可执行的机器指令(二进制指令)。

运行环境:代码实际执行的环境。

翻译环境

翻译环境实际上就包含两个过程:编译和链接。源代码文件通过编译器产生目标文件(.obj后缀),目标文件和链接库再通过链接器生成可执行程序(windows环境中为.exe后缀)。

编译

编译又可以分为三个过程:预处理(预编译)、编译和汇编。

预处理(预编译)

预处理也叫预编译,在gcc环境下,源文件经过预处理后会生成.i为后缀的文件。

预处理阶段主要处理那些预编译指令:包括头文件的包含、#define宏定义的文本替换,注释行的删除,条件编译的处理等。有很多,这里简单说几个。

在预处理阶段,我们声明的头文件(比如说<stdio.h>)中的内容会被展开成代码。

也就是说虽然我们实际写的代码只有十几行,但在.i文件中可能会展开成几百行或者上千行。

在预处理阶段我们用#define宏定义的符号会被替换掉,比如下列代码:

在预处理阶段就会被替换成这样:

替换完后该宏MAX就会被移除。

编译

编译阶段会把预处理产生的.i文件进行词法分析、语法分析、语义分析及优化,生成对应的汇编代码。

词法分析

比如说a=3+2;在词法分析阶段会被划分成一系列记号。

语法分析

在语法分析阶段,会生成对应的语法树:

语义分析

由语义分析器来完成语义分析,即对表达式的语法层面分析。这个阶段会报出错误的语法信息。

汇编

在汇编阶段会把编译产生的汇编代码转换为可执行的二进制指令,产生目标文件。

链接

链接是一个复杂的过程,是把所有文件链接在一起生成可执行程序。

链接包括地址和分配内存,符号决议的和重定位等步骤。

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

运行环境

  1. 程序必须载入内存中。在有操作系统的环境中:一般这个由操作系统完成。在独立的环境中,程序的载入必须由手工安排,也可能是通过可执行代码置入只读内存来完成。
  2. 程序的执行便开始。接着便调用main函数。
  3. 开始执行程序代码。这个时候程序将使用一个运行时堆栈(stack),存储函数的局部变量和返回地址。程序同时也可以使用静态(static)内存,存储于静态内存中的变量在程序的整个执行过程一直保留他们的值。
  4. 终止程序。正常终止main函数;也有可能是意外终止。
相关推荐
2601_962885727 小时前
如何用 Python 把 K 线重采样成任意周期?
开发语言·python
Wang's Blog7 小时前
Java 项目实战: 交友项目 - 圈子功能实现:总结
java·开发语言·交友
下一站春风里8 小时前
位运算完整学习笔记:按位与(&)+ 异或(^)
开发语言·c++·算法
天外飞雨道沧桑9 小时前
我在浏览器里练了一个 792 参数的大模型,它学会了补全 JavaScript
开发语言·javascript·ai·ecmascript·ai编程
hhhjhl9 小时前
Yup 跨端三方库仓颉适配全流程
java·开发语言
运维行者_9 小时前
网络监控工具怎么选?从设备监控到智能运维的能力清单
运维·服务器·开发语言·网络·人工智能·支持向量机·php
“AI国潮设计-小江”10 小时前
【AIGC实战】Python+SDXL打造“潮汕英歌舞IP”万能立牌插件,批量生成“发财元宝蛋糕”视觉营销方案(附源码)
开发语言·人工智能·python·prompt·aigc
lhbweilai11 小时前
分析FreeRTOS内核对象API的源码实现(八)
c语言·开发语言·stm32·单片机
努力努力再努力wz11 小时前
【C++高阶系列】C++20 协程底层原理:函数为什么能暂停?从状态机到 Task,彻底串起挂起、恢复与协程调度
开发语言·c++·c++20·1024程序员节
咩咩啃树皮11 小时前
JavaScript 中 this 指向为什么总在变?
开发语言·前端·javascript