编译的幕后花絮

为了理解编译器怎么把多个源文件编译成一个程序,需要拉开帷幕,看看编译器到底怎么工作。

编译的幕后花絮 - 图1

  • 预处理:修改代码。

编译的幕后花絮 - 图2

  • 编译:转换成汇编代码。

C语言看似底层,但计算机还是无法理解它。计算机只理解更低层的机器代码指令。而生成机器代码的第一步就是把C语言源代码转化为汇编语言代码,看起来像这样:

  1. movq -24(%rbp), %rax
  2. movzbl (%rax), %eax
  3. movl %eax, %edx

是不是很难懂?汇编语言描述了程序运行时中央处理器需要执行的指令。C编译器有很多食谱,覆盖了C语言的方方面面,比如如何把if语句或函数调用转化为一串汇编语言指令。但汇编语言还不够底层,所以我们需要……

编译的幕后花絮 - 图3

  • 汇编:生成目标代码。

编译器需要将这些符号代码汇编成机器代码或目标代码,即CPU内部电路执行的二进制代码。

编译的幕后花絮 - 图4

你已经把C语言源代码转化成电路所需的0和1了。还差最后一步,你给了编译器几个文件来编译程序,编译器会为每个源文件生成一个目标代码,为了生成可执行程序,还需要对这些目标文件做一件事……

编译的幕后花絮 - 图5

  • 链接:放在一起。

一旦有了全部的目标代码,就需要像拼“七巧板”那样把它们拼在一起,构成可执行程序。当某个目标代码的代码调用了另一个目标代码的函数时,编译器会把它们连接在一起。同时,链接还会确保程序能够调用库代码。最后,程序会写到一个可执行程序文件中,文件格式视操作系统而定,操作系统会根据文件格式把程序加载到存储器中运行。

编译的幕后花絮 - 图6

怎么让gcc知道我们想用几个单独的源文件生成可执行程序呢?