现代计算机的速度非常快,而且一直在变快。然而,计算机也有一些重要的限制:它们只能理解一组有限的命令,并且必须被告知要做什么。

计算机程序(通常也被称为应用程序)是一组计算机可以以执行一些任务执行的指令。创建程序的过程称为编程。程序员通常通过生成源代码(通常缩写为code)来创建程序,源代码是键入到一个或多个文本文件中的命令列表。

组成计算机并执行程序的物理计算机部件的集合称为硬件。当计算机程序加载到内存中,硬件依次执行每条指令时,这称为运行执行程序。

机器语言

计算机的CPU不能运行C++。CPU可以直接理解有限的指令集称为机器代码(或机器语言指令集)。

这是一个示例机器语言指令: 10110000 01100001

回到计算机刚发明的时候,程序员必须直接用机器语言编写程序,这是一件非常困难和耗时的事情。

这些说明的组织方式超出了本介绍的范围,但值得注意的是两件事。首先,每条指令由一串1和0组成。每个单独的0或1称为一个二进制数字,或简称。组成单个命令的位数各不相同——例如,某些CPU处理的指令长度始终为32位,而其他一些 CPU(例如您可能使用的 x86 系列)的指令可以是可变长度。

其次,每组二进制数字都被CPU解释成一个命令来完成一个非常具体的工作,比如比较这两个数字,或者把这个数字放在那个内存位置。但是,由于不同的CPU具有不同的指令集,因此无法在不共享相同指令集的CPU上使用为一种CPU类型编写的指令。这意味着程序通常不可移植(无需大量返工即可使用)到不同类型的系统,并且必须重新编写。

汇编语言

由于机器语言对人类来说很难阅读和理解,因此发明了汇编语言。在汇编语言中,每条指令都由一个简短的缩写(而不是一组位)标识,并且可以使用名称和其他数字。

这是与上面相同的汇编语言指令: mov al, 061h

这使得汇编比机器语言更容易阅读和编写。但是,CPU不能直接理解汇编语言。相反,汇编程序必须先翻译成机器语言,然后才能被计算机执行。这是通过使用称为汇编程序的程序来完成的。用汇编语言编写的程序往往非常快,当速度至关重要时,今天仍在使用汇编。

然而,汇编仍然有一些缺点。首先,即使是简单的任务,汇编语言仍然需要大量指令。虽然单个指令本身在某种程度上是人类可读的,但理解整个程序在做什么可能具有挑战性(这有点像试图通过单独查看每个字母来理解句子)。其次,汇编语言仍然不是很容易移植——用汇编语言为一个CPU编写的程序可能无法在使用不同指令集的硬件上运行,并且必须重新编写或大量修改。

高级语言

为了解决可读性和可移植性问题,开发了新的编程语言,如 C、C++、Pascal(以及后来的Java、Javascript和Perl等语言)。这些语言被称为高级语言,因为它们旨在允许程序员编写程序而不必担心程序将在哪种计算机上运行。

这是与上述C/C++相同的指令: a = 97;

就像汇编程序一样,用高级语言编写的程序必须先翻译成计算机可以理解的格式才能运行。有两种主要的方式来完成:编译和解释。

编译器是一个程序,读取源代码,并且产生然后可以运行一个独立的可执行程序。一旦您的代码变成可执行文件,您就不需要编译器来运行程序。一开始,编译器很原始,生成的代码很慢,未经优化。然而,多年来,编译器已经变得非常擅长生成快速、优化的代码,并且在某些情况下可以比人类在汇编语言中做得更好!

以下是编译过程的简化表示:

由于C++程序通常是编译的,我们很快就会更详细地探讨编译器。

一个解释器是一个程序,直接执行在源代码中的指令,而无需它们被编译成可执行文件。

第一,解释器往往比编译器更灵活,但在运行程序时效率较低,因为每次运行程序时都需要进行解释过程。这意味着每次运行程序时都需要解释器。

以下是解释过程的简化表示:

选读

可以在这里找到编译器与解释器的优点的很好比较。

大多数语言都可以编译或解释,但是,像 C、C++ 和Pascal这样的传统语言是编译的,而像Perl和Javascript这样的“脚本”语言则倾向于解释。有些语言,如Java,Pascal使用这两种语言。

高级语言有许多理想的特性。

首先,高级语言更容易阅读和编写,因为命令更接近我们每天使用的自然语言。其次,高级语言需要更少的指令来执行与低级语言相同的任务,使程序更简洁、更易于理解。在C++中,您可以a = b * 2 + 5;在一行中执行类似操作。在汇编语言中,这需要5或6条不同的指令。

第三,可以为许多不同的系统编译(或解释)程序,您不必更改程序以在不同的 CPU上运行(您只需为该 CPU 重新编译)。举个例子:

可移植性有两个一般例外。首先是许多操作系统(例如 Microsoft Windows)包含您可以在代码中使用的特定于平台的功能。这些可以使为特定操作系统编写程序变得更加容易,但代价是可移植性。在这些教程中,我们将避免使用任何特定于平台的代码。

一些编译器还支持特定于编译器的扩展——如果你使用这些扩展,你的程序将无法被其他不支持相同扩展的编译器编译而无需修改。一旦您安装了编译器,我们将在稍后详细讨论这些内容。