C语言进阶 源程序到执行程序的那些事

本文详细解析了一个C语言程序从源代码到可执行文件的全过程,包括预处理、编译、汇编和链接四个阶段。预处理涉及头文件包含和宏定义替换;编译阶段将C代码转化为汇编代码并进行符号汇总;汇编阶段将汇编代码转为机器指令;链接阶段合并段表,解决符号引用并生成最终的可执行文件。通过此过程,理解了程序如何在计算机中运行。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

C语言学到了现在,相信大家已经掌握了相当多的知识,会写很多程序,但是有一个问题始终没有解决,那就是:一个程序是如何运行起来的,在实现的过程中都发生了什么?在这篇博客中,将会为大家解决这些问题


程序的实现

在ANSI C的任何一种实现中,都存在两个不同的环境,一种是翻译环境,在这个环境中源代码会被转换成可执行的机器指令。另一种是执行环境,它负责把代码运行出来,画图理解如下:
在这里插入图片描述
test.c代码如下:

#include<stdio.h>

int main()
{
	printf("1 2 3 4 5 6 7 8 9 10\n");
}

可以看到这个代码很简单,就是打印一到十,但是这个打印结果是怎样呈现在我们的电脑上的,过程是什么样的?这就是接下来我们要说的重点:
首先,我们写的这几行代码就是源文件,叫test.c,但是这个test.c是不能直接被执行的,这个源文件要经过层层转化,变成.exe(可执行文件)才能够运行,那么这个过程就叫翻译环境。
我们可以看看啊
在这里插入图片描述

在储存项目的文件夹里面,首先是有一个test.c,这是我们的源文件,源文件很小啊,只有1KB。
在这里插入图片描述
在另一个文件夹中储存着经过转化后的可执行程序文件,足足有61KB,那在这个转化中到底发生了什么呢?

翻译环境

在这里插入图片描述
整个翻译流程的过程是这样的,实际上计算机可以多个程序同时编译,就像这样:
在这里插入图片描述
这样的过程多半在多个源文件,函数嵌套使用的时候会用到这个我们之后再说。
我们可以看到,源文件经过编译器的处理变成目标文件,目标文件通过链接器的处理形成可执行程序,那在编译和链接的过程中,发生了什么呢?

编译

在这里插入图片描述

其实在Linux环境中翻译的每一步都能呈现出来,但是由于笔者的Linux并不是很好,所以这里用VS替代。
预处理阶段
可以看到,编译也是分为三个阶段的,先看第一个预处理阶段,这个阶段会发生什么事情呢,第一点是头文件的包含,我们在写代码的时候,都会引用标准库,也就是#include<stdio.h>,光写这个代码是没有作用的,但是经过了预处理以后我们会把整个库都放到你的代码里面,你的代码突然就多了几百甚至上千行,感兴趣的可以自己在gcc中模拟一下。
第二点是宏定义符号的替换,也就是#define ,在写程序的时候,我们经常用 #define n 10这样的语句进行替换,但其实,n在预处理的时候,会被编译器重新替换成10.
在这里插入图片描述
在这里插入图片描述
可以看到,预处理之后程序发生了明显的变化,宏定义全被替换了,注释也没了,还会把stdio引用进来,这代码量一下子就上来了。
编译阶段
在编译阶段,编译器会根据一些规则,把你写的C语言代码,转换成汇编代码。
是这里是对你的语法,词法,语义进行分析,转化成汇编代码,这些如果学过编译原理的同学应该会很了解,但是编译阶段最重要的还是符号汇总
这个符号汇总呢,会统计一些全局的符号,例如main,又例如全局出现的函数名之类的,变量名不属于其中的范围,下面我们看个例子:
在这里插入图片描述
extern是一个关键字,说明该函数不是在这里声明的,去其他文件里边找。
看看这里的符号有哪些,在 test中,符号: add、main
在add中,符号:add
在编译阶段,我们会把这些符号先收集起来备用。
汇编
在汇编阶段,我们会把汇编指令转换成计算机所能识别的二进制指令,我们可以看看这些指令:
在这里插入图片描述
这是test.obj文件,我们是完全看不懂的,在转换的时候,还会形成符号表,就是在编译阶段的那个符号汇总。
在这里插入图片描述
这就是test和add的符号表,可以看到他们是有重复的,而且test.obj中的add是没有地址的,因为就不是从他这里声明的,所以地址为空啊,这里的地址只是举个例子,并不一定准确。
到这里,编译阶段就完成了。

链接

紧接着是链接阶段,链接阶段主要就做两件事,一件是合并段表,另一件事是符号表的合并与重定位:
在这里插入图片描述

这个过程并不难理解啊,先说说合并段表,在经过编译时,文件会从.c文件转化成.obj的二进制文件,每个二进制文件被分成了很多个段,代表着不同的功能,而在链接阶段要做的就是把这些段连起来
在这里插入图片描述
有点类似于这样,凑活看看。
链接的时候还会完成符号表的合并和重定向,这又是什么意思呢?
符合表的合并,那就是把多个文件的符号表合并成一个,在这个过程中,重复的会被合成一个,而且会重新寻址,之前说的没有声明的函数没有地址,在这里也会找打它被声明的文件,给上它一个地址,合并完大概是这样(还是add的那个例子)
在这里插入图片描述
就是这么一个效果,后面跟的是他的地址。

那么经过这个操作以后,.obj文件就成功的转化为了.exe的可执行文件。

碎碎念

由于笔者的能力问题,并没有深挖细节,十分惭愧,来日方长,学明白以后一定再深入细致的说明这些过程。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值