用某种编程语言编写的程序就称为源代码,保存源代码的文件称为源文件。因为源文件是简单的文本文件,所以用 Windows 自带的记事本等文本编辑器就可以编写。CPU 能直接解析并运行的不是源代码而是本地代码的程序。对 CPU 来说,母语就是机器语言,而转换成机器语言的程序就是本地代码。用任何编程语言编写的源代码,最后都要翻译成本地代码,否则 CPU 就不能理解。也就是说,即使是用不同编程语言编写的代码,转换成本地代码后,也都变成用同一种语言(机器语言)来表示了。
本地代码的内容是人类无法理解的。计算机就是把所有的信息作为数值的集合来处理的。计算机指令也是数值的罗列。这就是本地代码。
能够把 C 语言等高级编程语言编写的源代码转换成本地代码的程 序称为编译器。每个编写源代码的编程语言都需要其专用的编译器。将 C 语言编写的源代码转换成本地代码的编译器称为 C 编译器。编译器首先读入代码的内容,然后再把源代码转换成本地代码。编译器中就好像有一个源代码同本地代码的对应表。但实际上,仅仅靠对应表是无法生成本地代码的。读入的源代码还要经过语法解析、句法解析、语义解析等,才能生成本地代码。根据 CPU 类型的不同,本地代码的类型也不同。因而,编译器不仅和编程语言的种类有关,和 CPU 的类型也是相关的。因为编译器本身也是程序的一种,所以也需要运行环境。有一种交叉编译器,它生成的是和运行环境中的 CPU 不同的 CPU 所使用的本地代码。
编译器转换源代码后,就会生成本地文件。不过,本地文件是无法直接运行的。为了得到可以运行的 EXE 文件,编译之后还需要进行“链接”处理。“-W-c”是用来指定编译 Windows 用的程序的选项。选项是对编译器的指示。有时也称为“开关”。编译后生成的不是 EXE 文件,而是扩展名为“.obj”的目标文件 。把多个目标文件结合,生成 1 个 EXE 文件的处理就是链接,运行连接的程序就称为链接器 (linkage editor 或连结器)。
库文件指的是把多个目标文件集成保存到一个文件中的形式。链接器指定库文件后,就会从中把需要的目标文件抽取出来,并同其他目标文件结合生成 EXE 文件。外部符号是指其他目标文件中的变量或函数。通过源代码形式而是通过库文件形式和编译器一起提供的。这样的函数称为标准函数。之所以使用库文件,是为了简化为链接器的参数指定多个目标文件这一过程。通过以目标文件的形式或集合多个目标文件的库文件形式来提供函数,就可以不用公开标准函数的源代码内容。
与此相反,存储着目标文件的实体,并直接和 EXE 文件结合的库文件形式称为静态链接库。静态(static = 静态的)同动态(dynamic = 动态的)是相反的意思。
当程序加载到内存后,除此之外还会额外生成两个组,那就是栈和堆。栈是用来存储函数内部临时使用的变量(局部变量),以及函数调用时所用的参数的内存区域。堆是用来存储程序运行时的任意数据及对象的内存领域。栈及堆的相似之处在于,他们的内存空间都是在程序运行时得到申请分配的。不过,在内存的使用方法上,二者存在些许不同。栈中对数据进行存储和舍弃(清理处理)的代码,是由编译器自动生成的,因此不需要程序员的参与。使用栈的数据的内存空间,每当函数被调用时都会得到申请分配,并在函数处理完毕后自动释放。与此相对,堆的内存空间,则要根据程序员编写的程序,来明确进行申请分配或释放。栈和堆的大小,可以由程序员任意指定。在高级编程语言中,编译器会自动生成指定栈和堆大小的代码,并将其附加到程序中。无论是 C 语言还是 C++,如果没有在程序中明确释放堆的内存空间,那么即使在处理完毕后,该内存空间仍会一直残留。这个现象称为内存泄露 。