我试着更好地理解它们的区别。我在网上找到了很多解释,但它们倾向于抽象的差异而不是实际的影响。
我的大部分编程经验都是使用CPython(动态、解释型)和Java(静态、编译型)。然而,我知道还有其他种类的解释型和编译型语言。除了可以从编译型语言编写的程序分发可执行文件的事实外,每种类型都有什么优缺点吗?通常情况下,我听到人们争论解释型语言可以以交互方式使用,但我相信编译型语言也可以有交互式实现,对吧?
我试着更好地理解它们的区别。我在网上找到了很多解释,但它们倾向于抽象的差异而不是实际的影响。
我的大部分编程经验都是使用CPython(动态、解释型)和Java(静态、编译型)。然而,我知道还有其他种类的解释型和编译型语言。除了可以从编译型语言编写的程序分发可执行文件的事实外,每种类型都有什么优缺点吗?通常情况下,我听到人们争论解释型语言可以以交互方式使用,但我相信编译型语言也可以有交互式实现,对吧?
一门语言本身既不是编译型的也不是解释型的,只有语言的具体实现才是。Java就是一个完美的例子。它有基于字节码的平台(JVM)、本地编译器(gcj)以及一个针对Java超集的解释器(bsh)。那么Java现在是什么?是字节码编译、本地编译还是解释执行?
其他既编译又解释的语言包括Scala、Haskell或Ocaml。这些语言都有交互式解释器,同时也有编译器将代码编译成字节码或本地机器码。
因此,通常按“编译型”和“解释型”来分类语言并没有太多意义。
开始从一个过去的角度思考:过去的影响
很久很久以前,在计算机译者和编译器的土地上生活着。各种各样的争论围绕着一个比另一个更好的优点展开。当时的普遍观点大致是:
在解释程序和编译程序之间存在一到两个数量级的运行时性能差异。其他区别点,例如代码的运行时可变性,也具有一定的兴趣,但主要区别围绕运行时性能问题。
今天,局面已经发展到了编译和解释的区别基本上无关紧要。许多编译语言调用的运行时服务不完全基于机器代码。此外,大多数解释语言在执行之前都会“编译”为字节码。字节码解释器可以非常高效,并在执行速度上与一些编译器生成的代码相媲美。
经典的区别是编译器生成本机机器代码,解释器读取源代码并使用某种运行时系统即时生成机器代码。今天几乎没有经典的解释器了 - 几乎所有解释器都编译成字节码(或其他半编译状态),然后在虚拟“机器”上运行。
极端简单的情况:
编译器将生成使用目标机器本地可执行格式的二进制可执行文件。除了系统库之外,这个二进制文件包含所有所需资源;它已经准备好运行,没有进一步的准备和处理,并且因为代码是目标机器 CPU 的本机代码,所以它运行非常快。
解释器会在循环中呈现一个提示符,用户可以在其中输入语句或代码,然后按下RUN
或等效项,解释器将检查、扫描、解析并逐行执行每个程序,直到程序运行到停止点或错误。由于每行都是独立处理的,而解释器不会从之前看到的代码中“学习”任何东西,所以将人类可读语言转换为机器指令的工作需要针对每行每次重复进行,因此速度比较慢。但是,用户可以以各种方式检查和互动他的程序:更改变量、更改代码、以跟踪或调试模式运行等。
这些已经弄清楚了,现在让我解释一下,生活不再那么简单了。例如,
现在,解释和编译已经成为一个权衡取舍的问题。编译代码只需花费一次时间,但可以获得更好的运行时性能;而解释环境更加交互式。编译与解释的主要区别是将"理解"程序的工作如何分配给不同的过程,如今随着语言和产品试图提供最佳方案,两者之间的界限已经变得模糊。
我认为这是计算机科学中最被误解的事情之一。因为解释和编译完全是两个不同的过程,我们不能用这种方式进行比较。
机器级别解释 - 这种解释发生在已经编译成机器代码的代码上。指令由处理器直接解释。像 C/C++ 这样的编程语言生成的是可由处理器执行的机器代码。因此,处理器可以直接执行这些指令。
虚拟机级别解释 - 这种解释发生在未编译为机器级别(处理器支持)代码而是编译为某些中间级别代码的代码上。这个执行是由另一个软件执行的,它是由处理器执行的。此时,处理器实际上看不到我们的应用程序。它只是执行虚拟机,而虚拟机在执行我们的应用程序。像 Java、Python、C# 这样的编程语言生成的是可由虚拟解释器/机器执行的字节码。
因此,最终我们必须理解的是,世界上所有编程语言都应该在某个时刻被解释。 它可以由处理器(硬件)或虚拟机执行。
编译只是将我们编写的高级代码(可被人类理解的)转换为某种硬件/软件可理解的水平的过程。
这些完全是两回事,我们无法进行比较。但是这种术语对于教授初学者如何处理编程语言非常有用。
PS:
一些编程语言如 Java 采用混合方法来实现这一点。首先,将高级代码编译成虚拟机可读的字节码。然后,在运行过程中,一个名为 JIT 编译器的组件将字节码编译成机器代码。特别是经常执行的代码行被翻译为机器语言,这使得解释过程更快。因为硬件处理器总是比虚拟解释器/处理器快得多。
《Python Book》© 2015 Imagine Publishing Ltd,通过第10页提到的以下提示来简单区分:
解释型语言(如Python)是指每次程序运行时源代码都会被转换为机器码然后执行。这与编译型语言(如C)不同,编译型语言只在源代码被转换为机器码一次后,每次程序运行时直接执行生成的机器码。