c语言的编译和运行
虚拟内存与物理内存
- 物理内存
作为计算机存储器件,用于与CPU内存管理单元和硬盘传递数据
现代DDR由SDRAM发展而来,属于同步动态随机存储器。 - 虚拟内存
每一个计算机的进程(程序)单独享用一片主存,但这是虚拟内存带来的幻觉。
这样的欺骗很有助于硬件和软件的隔离,便于内存管理
虚拟内存由操作系统管理,虚拟内存中有这些区
程序代码和数据
堆(低位递增)
共享库(动态链接库)
栈(高位递减)
内核虚拟内存
注:在虚拟内存地址空间中,堆从低地址向高地址增长,栈从高地址向低地址增长
虚拟内存通过映射与物理内存联系
c语言程序的编译和运行
c语言从编辑器编辑的.c文件,在预处理器中成为.i文件,通过编译器编译成为.s汇编语言,在汇编器翻译为.o(.obj)二进制机器码,最后链接器链接成为.exe可执行文件
编译
预处理
预处理的过程可以理解为预处理器的替换,处理所有的预编译指令#
- 将所有引用的库文件
#include<>的语句替换为该库文件 - 完成
#if #elseif #endif的条件编译的判断 - 展开
#define宏定义 - 保留
#pragma,这是给编译器的编译指令
编译
- 扫描:给源代码做记号,将记号分为关键字、标识符、变量名、运算符等
- 语法检查:将各种记号连接成表达式,检查表达式的正确性
- 语义检查:这里的检查会生成一些warning,例如 数组越界,指针的无意义运算,类型不匹配等
- 代码优化:不同的编译器对代码的优化是有差异的。
有时候我们并不希望编译器产生未知的优化,需要阻止编译器的优化。(volatile关键字)
汇编
类Unix系统编译的结果生成.o文件,Windows系统生成的是.obj文件
- 汇编器与目标CPU紧密相关,不同CPU需要不同的汇编器。不同架构CPU的汇编器的差异使得嵌入式开发中需要用CPU对应的交叉编译工具链去编译可执行程序。
链接
这里的链接是对静态库的链接,链接器也为静态链接器就是将翻译成的二进制文件与需要用到的库绑定在一块
链接器将.o和.a文件根据函数调用关系链接在一起
运行

.text : 二进制代码存储
.bss 和 .data 全局变量区
heap 作为动态内存,用malloc和free等动态管理
stack :用于局部变量,函数实参,函数返回值的存储
- 程序运行时,.exe文件加载进入主存.text
- 在.bss 和 .data中 创建全局变量
- 压main返回点入栈,程序开始
- 函数调用时,栈中压入函数返回地址(即函数执行完成后,程序需回到的原代码执行位置);函数执行结束时,返回地址从栈中弹出,程序依据该地址跳回原执行流程。
- 静态变量的创建放在全局变量区。
- main函数出栈(return 0),程序结束。

浙公网安备 33010602011771号