我已经用 C 编程有一段时间了,我想知道为什么分离这个过程(编译和链接)很重要?
有人可以解释一下吗?
它对于减少重建时间很有用。如果您只更改一个源文件 - 通常不需要重新编译整个项目,而只需重新编译一个或几个文件。
现在它可能不像以前那么重要了。
但是曾经有一段时间,编译一个项目实际上可能需要几天时间 - 在 20 世纪 80 年代,我们曾经在一个周末完成“完整构建”。仅仅解析单个文件的源代码是一件相当大的事情,需要大量的时间和内存,因此语言的设计使得它们的模块(源文件)可以被隔离处理。
结果是“目标文件” -
.obj
(DOS/Windows/VMS) 和 .o
(unix) 文件 - 其中包含可重定位代码、静态数据和导出列表(我们定义的对象)和导入(我们需要的对象)。链接阶段将所有这些粘合在一起形成可执行文件或归档(.lib
、.a
、.so
、.dll
文件等)以供进一步包含。
使昂贵的编译任务独立运行导致了复杂的增量构建工具(如
make
)的出现,它显着提高了程序员的生产力——对于大型 C 项目(如 Linux 内核)仍然至关重要。
它还意味着任何可以编译成目标文件的语言都可以链接在一起。因此,只需付出一点努力,就可以将 C 链接到 Fortran、COBOL、C++ 等等。
自那时以来开发的许多语言都突破了目标文件中可以存储的内容的界限。 C++ 模板系统需要特殊处理,并且重载方法不太适合,因为普通
.o
文件不支持具有相同名称的多个函数(请参阅 C++ 名称修饰)。 Java 等人使用了完全不同的方法,使用自定义代码文件格式和粘合到 DLL 和共享对象文件上的“本机代码”调用机制。
因为,编译负责将每个源代码文件的源代码转换为相应的目标代码。就是这样。因此编译器不必关心外部符号(如库和
extern
变量)。
链接负责查找这些引用,然后生成单个二进制文件,就像您的项目被编写为单个源代码文件一样。 (我还建议您参考维基百科linking页面以了解静态链接和动态链接之间的区别)
如果您碰巧使用该工具
Make
,您会发现每当您调用make
时它不会重新编译每个文件,它会查找自上次构建以来修改了哪些文件,然后仅重新编译它们。然后调用链接过程。当您处理大型项目(例如 Linux 内核)时,这可以节省大量时间。
实际上,这根本不重要。特别是对于更简单的程序,这两个步骤都是通过一个程序调用来执行的,例如
gcc f1.c f2.c f3.c f4.c -o program
它从这些源文件创建可执行文件
program
。
但事实仍然是,这些是单独的过程,在某些情况下值得注意这一点。
我曾经开发过需要两天才能编译的系统。你不想做一点小改变就必须等待 2 天来测试。