前言:
在任何标准的C语言实现中,存在两个不同的环境,其中一个是翻译环境,这个过程中会将我们源代码转换成可执行的机器指令;另一个是执行环境,这个过程就是执行我们的代码了。 接下来我会简单的介绍下翻译环境的大概思路以及过程。
目录
编译链接大致流程图:
介绍流程图:
上图中大概的描述了编译和链接过程,说是多个源文件经过编译器生成的多个目标文件,然后链接库和多个目标文件经过链接器生成可执行程序。
编译分为的三个阶段:(1)预编译 (也叫预处理) (2)编译 (3)汇编
(1)预编译阶段
先看下面代码,预处理会有什么结果
补充:VS是一个集成的编译器,不能直接观察到我们的预处理阶段,因此改一下设置,如以下图:
#include <stdio.h>
#define M 9
#define N 4
int g_val = 6;
int main()
{
int a = M;
int b = N;
//调用Add函数
int sum = Add(a, b);
printf("%d %d", sum, g_val);
return 0;
}
在我们运行预处理后会观察到我们的文件路径下有一个 .i的文件打开就是预处理后的代码如下图:
当我们经过两个对比后会发现我们 #define 定义的直接被替换掉,而注释也没有了,并生成了1万多行的代码,这是由于我多掉了几次<stdio.h> 这样的话会导致 重复调用,因此可以观察到我们预处理的会有三个明显的特征:
特征一:头文件会被包含。
特征二:#define定义的符号替换,并删除定义符号。
特征三:注释删除
(2)编译阶段
汇编阶段目前我不知道如何在VS下观察,因此只能简单介绍下这个过程的特征:
特征一:生成后缀.s的文件。
特征二:将我们C语言代码转换成汇编代码。
特征三:进行语法分析,词法分析,语义分析,符号汇总。
补充:变量的名字和函数的名字称为符号。由预处理阶段可观察到我们的全局变量,main函数,自定义函数都没有去掉,因此可以说此时生成的符号是这些。
(3) 汇编阶段
汇编阶段的特征
特征一:生成后缀.o的文件。
特征二:把汇编代码转换成二进制指令。
特征三:将编译阶段的符号形成符号表。(添加了地址)
(4)链接阶段
链接阶段的特征
特征一: 合并段表。(像多个这样test.o的文件 和 链接库 合并)
特征二: 符号表的合并和重定义(存在多个源文件,我们上述过程只写了一个)。
补充:符号表的合并和重定义是为了让多个源文件有准确的目标地址,并且可以找得到
执行环境:
程序执行过程中有以下流程
流程一:程序载入内存时,分两种情况。
①有操作系统环境:一般由操作系统完成。
②独立的环境:程序载入必须手工安排。(也可通过可执行代码置入内存来完成)
流程二:程序执行便开始,接着调用main函数。
流程三:开始执行程序代码。
流程四:正常终止程序。(也有可能意外终止)