1.3 了解编译系统如何工作是大有益处的

对于像 hello.c 这样简单的程序,我们可以依靠编译系统生成正确有效的机器代码。但是,有一些重要的原因促使程序员必须知道编译系统是如何工作的。

  • 优化程序性能。现代编译器都是成熟的工具,通常可以生成很好的代码。作为程序员,我们无须为了写出高效代码而去了解编译器的内部工作。但是,为了在 C 程序中做出好的编码选择,我们确实需要了解一些机器代码以及编译器将不同的 C 语句转化为机器代码的方式。比如,一个 switch 语句是否总是比一系列的 if-else 语句高效得多?一个函数调用的开销有多大?while 循环比 for 循环更有效吗?指针引用比数组索引更有效吗?为什么将循环求和的结果放到一个本地变量中,会比将其放到一个通过引用传递过来的参数中,运行起来快很多呢?为什么我们只是简单地重新排列一下算术表达式中的括号就能让函数运行得更快??

    在第3章中,我们将介绍 x86-64,最近几代 Linux、Macintosh 和 Windows 计算机的机器语言。我们会讲述编译器是怎样把不同的 C 语言结构翻译成这种机器语言的。在第 5 章中,你将学习如何通过简单转换C语言代码,帮助编译器更好地完成工作,从而调整 C 程序的性能。在第 6 章中,你将学习存储器系统的层次结构特性,C 语言编译器如何将数组存放在内存中,以及 C 程序又是如何能够利用这些知识从而更高效地运行。

  • 理解链接时出现的错误。根据我们的经验,一些最令人困扰的程序错误往往都与链接器操作有关,尤其是当你试图构建大型的软件系统时。比如,链接器报告说它无法解析一个引用,这是什么意思?静态变量和全局变量的区别是什么?如果你在不同的 C 文件中定义了名字相同的两个全局变量会发生什么?静态库和动态库的区别是什么?我们在命令行上排列库的顺序有什么影响?最严重的是,为什么有些链接错误直到运行时才会出现?在第 7 章中,你将得到这些问题的答案。

  • 避免安全漏洞。多年来,缓冲区溢出错误是造成大多数网络和 Internet 服务器上安全漏洞的主要原因。存在这些错误是因为很少有程序员能够理解需要限制从不受信任的源接收数据的数量和格式。学习安全编程的第一步就是理解数据和控制信息存储在程序栈上的方式会引起的后果。作为学习汇编语言的一部分,我们将在第 3 章中描述堆栈原理和缓冲区溢出错误。我们还将学习程序员、编译器和操作系统可以用来降低攻击威胁的方法。

最后更新于