C源代码是如何跑起来的?

  • 2019 年 12 月 25 日
  • 笔记

本文 1273 个字,预计阅读 5 分钟

身为程序猿,C 语言大家一定都不陌生了,还记得当年在黑窗口中第一次显示出 hello, wordl! 时激动的心情吗?平时我们在写 C 程序时都用 IDE(集成开发环境),写好源代码之后点一下按钮,一键运行。但是不同的 IDE 会出现不同的按钮,甚至还有多个按钮,什么先点编译,后点运行(当时老师就是这么说的,咱也不知道为什么,照着做就是了)。

随着越来越深入了解计算机,我逐渐地明白了其中的执行过程,看似写好的 C 代码点一下就可以运行,其实这都是 IDE 帮我们集成好的,它私下里偷偷地帮我们做了许多工作呢。让我们一起来看看 C 源代码是如何跑起来的。

C 程序从源代码到运行阶段一共需要进行如下几个阶段。

那究竟是怎样进行的呢?我们一起来看一看。

我们在 Ubuntu 上用 gcc 编译器对 C 代码进行处理。首先用 vim 写一个 C 程序,就写最简单的 hello, world 吧。

1.

进行预处理,调用预处理器,使用命令 gcc -E hello.c -o hello.i

现在生成了一个名为 hello.i 的文件,打开来看一下有什么变化。

可以看到,在源代码的基础上,#include<stdio.h> 所在的语句没有了,与之替换的是一堆声明,增加了几百行,也就是说,在预处理阶段,预处理器会将我们 C 源代码中的所有宏定义(带 # 符号的语句)进行替换。

2.

进行编译,调用编译器,使用命令 gcc -S hello.i -o hello.s

现在生成了一个名为 hello.s 的文件,打开看一看。

如果你学过汇编语言的话,就会很熟悉,这里全部都是汇编语言。在编译阶段,编译器会将刚才经过预处理器处理过的文件进行编译,将 C 代码(高级语言)翻译成汇编语言代码(低级语言)。

3.

进行汇编,调用汇编器,使用命令 gcc -c hello.s -o hello.o

生成了 hello.o 文件(该文件是可重定位目标文件),这里如果我们再用文本编辑软件打开该文件,会发现一堆乱码,因为现在该文件已经是二进制文件,文本编辑软件只能查看文本文件,如果按照文本解析的方式解析二进制文件就会产生乱码。在预处理、编译阶段,我们都可以查看其生成的文件,只有在汇编这一步打开会产生乱码,我们可以知道,汇编器将汇编语言代码翻译成二进制文件。因为计算机只能执行二进制文件。

到目前为止,已经生成了二进制文件 hello.o, 如果你去运行,一定会报错,这是因为还差最后一步——链接。

4.

链接的作用是干什么呢?还记得我们之前写代码时调用的 printf() 函数吗?这个函数是在标准库中定义的,我们写 hello.c 源代码时没有对它进行定义,只对它进行调用,C 程序不认识这个函数,想要让 C 程序认识这个函数就必须找到它定义的位置,链接就是负责把我们在源代码中调用的函数从它定义的文件中加载过来

5.

链接完成之后,我们就可以调用加载器对该程序进行加载运行,最激动人心的时刻就要到来了,经过一系列复杂的步骤,屏幕上终于显示出了 Hello, world!

嗨,你还在看吗?