2-1 语言的翻译过程

224 阅读5分钟

概述

用户定义的数据类型或类,是C++区别于传统过程型语言的地方。类是一种新的数据类型,用来解决特定问题。

2.1 语言的翻译过程

  任何一种计算机语言都要从某种人们容易理解的形式(源代码)转化成计算机能执行的形式(机器指令)。通常,翻译器分为两类:解释器(interpreter)编译器(compiler)

2.1.1 解释器

  解释器将源代码转化成一些动作(它可由多组机器指令组成)并立即执行这些动作。
  使用解释器有许多好处。从写代码到执行代码的转换几乎能立即完成,并且源代码总是现存的,所以一旦出现错误,解释器能很容易地指出。对于解释器,较好的交互性和适于快速程序开发(不必要求可执行程序)也是常被提到的两个优点。
  当做大项目时解释性语言有某些局限性。解释器必须驻留内存以执行程序,而这样一来,即使是最快的解释器其速度也会变得让人难以接受。大部分的计时器要求一次输入整个源代码。这不仅造成内存空间的限制,而且如果语言不提供设施来隔离不同代码段之间的影响,一旦出现错误,就很难调试。

2.1.2 编译器

  编译器直接把源代码转化成汇编语言或机器指令。最终的结果是一个或多个机器代码的文件。这是一个复杂的过程,通常分几步完成。
  某些语言可以分别编译各段程序。最后使用连接器把各段程序连接成一个完整的可执行程序。这个过程称为分段编译。
  分段编译有许多好处。每次穿件和测试程序的一部分,当这部分程序能正常运行后,就把它作为程序组块保存起来。人们把测试通过并能正常运行的程序块收集起来加入库中,供其他程序员使用。

2.1.3 编译过程

  某些语言编译时,首先要对源代码执行预处理。预处理器是一个简单的程序,它用程序员(利用预处理器指令)定义好的模式代替源代码中的模式。预处理器指令用来节省输入,增加代码的可读性。预处理过的代码通常存放在一个中间文件中。
  编译一般分两遍进行。首先,对预处理过的代码进行语法分析。编译器把源代码分解成小的单元并把它们按树形结构组织起来。
  有时候会在编译的第一遍和第二遍之间使用全局优化器来生成更短、更快的代码。
  编译的第二遍,由代码生成器遍历语法分析书,把树的每个节点转化成汇编语言或机器语言。如果代码生成器生成的是汇编语言,那么还必须用汇编器对其汇编。两种情况的最终结果都是生成目标模块(通常是,一个以.o或.obj为扩展名的文件)。有时也会在第二遍中使用窥孔优化器(peephole optimizer )从性in一段代码中查找冗余汇编语句。
  连接器(linker)把一组目标模块连接成为一个可执行程序,操作系统可以装载和运行它。当某个目标模块中的函数要引用另一目标模块中的函数或变量时,由连接器来处理这些引用;这就保证了所有需要的、在编译时存在的外部函数和变量仍然存在。连接器还要添加一个特殊的目标模块来完成程序启动任务。
  连接器能搜索称为“库”的特殊文件来处理它的所有引用。库将一组目标模块包含在一个文件中。库由一个被称为**库管理器(librarian)**的程序来创建和维护。

2.1.3.4 静态类型检查

  类型检查(type checking) 是编译器在第一遍中完成的。类型检查是检查函数参数是否正确使用,以防止许多程序设计错误。由于类型检查是在编译阶段而不是程序运行阶段进行的,所以称之为静态类型检查。
  某些面向对象的语言(如Java)也可以在程序运行时作部分类型检查【动态类型检查】。动态类型检查和静态类型检查结合使用,比仅仅使用静态类型检查更有效。但它也增加了程序执行的开销。
  C++使用静态类型检查,因为C++语言不采用任何特殊的运行时支持来处理错误操作。静态类型检查在编译时就告知程序员类型被误用,从而加快了执行时的速度。C++语言的主要设计目标也是追求运行速度快。
  在C++里可以不使用静态类型检查。我们可以自己做动态类型检查-这只需要写一些代码。