我想更好地理解其中的区别。我在网上找到了很多解释,但它们都倾向于抽象的差异,而不是实际的含义。
我的大部分编程经验都是使用CPython(动态的,解释的)和Java(静态的,编译的)。然而,我知道还有其他类型的解释语言和编译语言。除了可执行文件可以从编译语言编写的程序中分发之外,每种类型有什么优点/缺点吗?我经常听到有人说解释型语言可以交互式地使用,但我相信编译型语言也可以有交互式实现,对吗?
首先,澄清一下,Java不是完全静态编译和以c++的方式链接的。它被编译成字节码,然后由JVM解释。JVM可以对本机机器语言进行即时编译,但不必这样做。
更重要的是:我认为交互性是主要的实际区别。由于所有内容都是解释的,所以您可以截取一小段代码,解析并根据环境的当前状态运行它。因此,如果您已经执行了初始化变量的代码,则可以访问该变量,等等。它真的很适合函数式风格。
然而,解释成本很高,特别是当您有一个包含大量引用和上下文的大型系统时。根据定义,这是一种浪费,因为相同的代码可能必须解释和优化两次(尽管大多数运行时都为此进行了缓存和优化)。不过,您仍然需要支付运行时成本,并且经常需要运行时环境。您也不太可能看到复杂的过程间优化,因为目前它们的性能还没有充分的交互性。
因此,对于不会有太大变化的大型系统,以及某些语言,更有意义的是预编译和预链接所有内容,做所有可以做的优化。最终会得到一个非常精简的运行时,该运行时已经针对目标机器进行了优化。
至于生成可执行文件,恕我直言,这一点关系不大。通常可以从编译语言创建可执行文件。但是您也可以使用解释语言创建可执行文件,只不过解释器和运行时已经打包在可执行文件中,并且对您隐藏了。这意味着您通常仍然需要支付运行时成本(尽管我确信对于某些语言,有方法将所有内容转换为可执行树)。
我不同意所有的语言都可以互动。某些语言,如C语言,与机器和整个链接结构紧密相连,我不确定您是否能够构建一个有意义的完整的交互式版本
很难给出一个实际的答案,因为差异在于语言定义本身。可以为每一种编译语言构建一个解释器,但不可能为每一种解释语言构建一个编译器。它主要是关于语言的正式定义。所以在大学里没有人喜欢理论信息学。
极端和简单的情况:
编译器将以目标机器的本机可执行格式生成二进制可执行文件。这个二进制文件包含除系统库之外的所有必需资源;它已经准备好运行了,不需要进一步的准备和处理,它运行起来像闪电一样,因为代码是目标机器上CPU的本机代码。
解释器将在循环中为用户提供一个提示符,用户可以在其中输入语句或代码,在点击RUN或等效值时,解释器将检查、扫描、解析并解释性地执行每一行,直到程序运行到一个停止点或出现错误。因为每一行都是单独处理的,解释器不会从之前看到的行中“学习”到任何东西,所以每一行都需要将人类可读的语言转换为机器指令,所以它非常缓慢。好的一面是,用户可以以各种方式检查程序并与程序交互:更改变量、更改代码、在跟踪或调试模式下运行……无论什么。
RUN
说完了这些,让我来解释一下,生活不再那么简单了。例如,
最后,现在,解释和编译是一种权衡,花费(一次)编译的时间通常会获得更好的运行时性能,但解释环境提供了更多的交互机会。编译与解释主要是“理解”程序的工作如何在不同的过程之间划分的问题,而如今,由于语言和产品试图提供两者的最佳服务,这条界线有点模糊。
编译语言是这样一种语言:程序一旦编译,就用目标机器的指令来表达。例如,源代码中的加法“+”操作可以直接转换为机器代码中的“ADD”指令。
解释型语言是指指令不直接由目标机器执行,而是由其他程序读取和执行的语言(通常是用本机语言编写的是)。例如,相同的“+”操作将在运行时被解释器识别,然后调用它自己的“add(a,b)”函数,并使用适当的参数,然后执行机器代码“add”指令。
你可以在编译语言中做你在解释语言中可以做的任何事情,反之亦然——它们都是图灵完备的。然而,这两种方法在实施和使用方面都有优点和缺点。
我将完全概括(纯粹主义者原谅我!),但大致来说,以下是编译语言的优点:
下面是解释型语言的优点:
注意,字节码编译等现代技术增加了一些额外的复杂性——这里发生的情况是,编译器的目标是一个与底层硬件不同的“虚拟机”。这些虚拟机指令可以在稍后阶段再次编译,以获得本机代码(例如,由Java JVM JIT编译器完成)。
编译器和解释器做同样的工作:将一种编程语言翻译成另一种编程语言,通常更接近硬件,通常是直接可执行的机器代码。
传统上,“编译”意味着这个转换是由开发人员完成的,并将生成的可执行文件分发给用户。纯例子:c++。 编译通常花费相当长的时间,并尝试进行大量昂贵的优化,以使生成的可执行文件运行得更快。最终用户不具备自己编译的工具和知识,而可执行文件通常必须在各种硬件上运行,因此您无法进行许多特定于硬件的优化。在开发过程中,单独的编译步骤意味着更长的反馈周期
传统上,“解释的”意味着当用户想要运行程序时,翻译是“动态的”。纯示例:香草PHP。一个简单的解释器在每次运行时都必须解析和翻译每一段代码,这使得它非常缓慢。它不能做复杂的、昂贵的优化,因为它们花费的时间比节省的执行时间要长。但它可以充分利用其所运行的硬件的功能。缺少单独的编译步骤减少了开发过程中的反馈时间。
但是现在“编译还是解释”已经不是一个非黑即白的问题了,在两者之间有一些阴影。天真、简单的解释器几乎绝迹了。许多语言使用两步过程,其中高级代码被转换为与平台无关的字节码(解释起来要快得多)。然后是“及时编译器”,每次程序运行最多编译一次代码,有时缓存结果,甚至智能地决定解释很少运行的代码,并对运行大量的代码进行强大的优化。在开发过程中,调试器能够在正在运行的程序中切换代码,即使对于传统编译语言也是如此。
语言本身既不编译也不解释,只有语言的特定实现才是。Java就是一个很好的例子。有一个基于字节码的平台(JVM)、一个本机编译器(gcj)和一个用于Java超集(bsh)的互用器。那么Java现在是什么呢?字节码编译,本机编译还是解释?
其他既编译又解释的语言有Scala、Haskell或Ocaml。每种语言都有一个交互式解释器,以及一个字节码或本机机器码的编译器。
所以一般来说,用“编译型”和“解释型”来划分语言并没有多大意义。
开始考虑a: 来自过去的冲击波
运行时的一个或两个数量级的差异 解释程序和编译程序之间存在性能差异。其他的区别 点,例如代码的运行时可变性,也有一些兴趣,但主要是 区别围绕着运行时性能问题
今天的情况已经发展到这样的程度,编译/解释的区别是 几乎无关紧要。许多 编译语言调用的运行时服务并非如此 完全基于机器代码。而且,大多数解释型语言都被“编译”成字节码 之前执行。字节码解释器非常高效,可以与一些编译器生成的解释器相匹敌 从执行速度的角度看代码 经典的区别是编译器生成本机机器码,解释器读取源代码和 使用某种运行时系统动态生成机器代码。 如今,经典的诠释者已所剩无几——几乎全部 编译成字节码(或其他一些半编译状态),然后在虚拟“机器”上运行
解释源代码相对于编译源代码的最大优势是可移植性。
如果你的源代码是编译的,你需要为你的程序运行在不同类型的处理器和/或平台编译不同的可执行文件(例如一个用于Windows x86,一个用于Windows x64,一个用于Linux x64,等等)。此外,除非您的代码完全符合标准,并且不使用任何特定于平台的函数/库,否则您实际上需要编写和维护多个代码库!
如果你的源代码是解释型的,你只需要编写一次,它就可以在任何平台上由合适的解释器解释和执行!可移植的 !注意解释器本身是是为特定平台编写和编译的可执行程序。
编译代码的一个优点是它从最终用户隐藏源代码(可能是知识产权),因为不是部署人类可读的原始源代码,而是部署一个模糊的二进制可执行文件。
从http://www.quora.com/What-is-the-difference-between-compiled-and-interpreted-programming-languages
没有区别,因为“编译编程语言”和 “解释性编程语言”不是有意义的概念。任何 编程语言,我的意思是任何一种,都可以被解释或 编译。因此,解释和编译都是实现 .技术,而不是语言属性 解释是一种技术,通过这种技术,另一个程序 解释器,代表所运行的程序执行操作 为了运行它而进行解释。如果你能想象阅读一个程序 按照上面说的一步一步地做,比如说在一张白纸上 纸,这也是口译员的工作。一个常见的原因 对程序进行解释是口译员比较容易做到的 写。另一个原因是,解释器可以监视 程序试图在运行时执行策略,例如 安全。< / p > 编译是一种用一种语言编写程序的技术 (源语言)被翻译成另一种语言的程序 语言(“目标语言”),希望意思是一样的 如原程序。在做翻译时,常见的是 编译器也会尝试以某种方式转换程序 使目标程序更快(不改变其含义!)一个 编译程序的常见原因是有一些好的方法 用目标语言快速运行程序,而且没有开销 根据上面的定义,您可能已经猜到,这两个 实现技术不是相互排斥的,甚至可能是 互补的。传统上,编译器的目标语言是 机器代码或类似的东西,它指的是任意数量的 特定计算机cpu所理解的编程语言。的 然后机器代码将“在金属上”运行(尽管有人可能会看到,如果 仔细观察,“金属”的工作原理很像 翻译)。然而,今天,使用编译器来 生成要被解释的目标代码——例如,这个 是Java过去(有时仍然是)的工作方式。有 将其他语言翻译成JavaScript的编译器 通常在web浏览器中运行,它可以解释JavaScript,或者 将其编译为虚拟机或本机代码。我们也有翻译 对于机器代码,可以用来模拟一种硬件 另一个地方。或者,可以使用编译器生成目标代码 然后是另一个编译器的源代码,它甚至可以编译 代码在内存中正好为它运行,这反过来…你得到 这个想法。 . .
没有区别,因为“编译编程语言”和 “解释性编程语言”不是有意义的概念。任何 编程语言,我的意思是任何一种,都可以被解释或 编译。因此,解释和编译都是实现
The Python Book©2015 Imagine Publishing Ltd,简单地通过第10页中提到的以下提示来区分差异:
像Python这样的解释型语言是指将源代码转换为机器码,然后在每次程序运行时执行的语言。这与编译语言(如C)不同,后者只将源代码转换为机器代码一次——然后在程序每次运行时执行生成的机器代码。
简短的(不精确的)定义:
整个程序立即转换为机器代码,然后机器代码由CPU运行。
解释语言:程序是逐行读取的,一旦读取一行,CPU就会执行该行的机器指令。
但实际上,现在很少有语言是纯编译或纯解释的,它们通常是混合的。想要更详细的图片描述,请看这个帖子:
编译和解释的区别是什么?< / >
或者是我后来的博客:
https://orangejuiceliberationfront.com/the-difference-between-compiler-and-interpreter/
机器级解释-这种解释发生在编译成机器代码的代码上。指令由处理器直接解释。像C/ c++这样的编程语言生成机器代码,由处理器执行。所以处理器可以直接执行这些指令。
虚拟机级解释-这种解释发生在没有编译成机器级(处理器支持)代码的代码上,而是编译成一些中间级别的代码。这个执行是由另一个软件完成的,该软件由处理器执行。此时处理器看不到我们的应用程序。它只是执行虚拟机,也就是执行我们的应用程序。Java、Python、c#等编程语言生成字节代码,虚拟解释器/机器可执行这些代码。
所以在一天结束的时候,我们必须理解的是,世界上所有的编程语言在某个时候都应该被解释它可能是由处理器(硬件)或虚拟机完成的。
编译只是将我们编写的人类可理解的高级代码带到机器可理解的硬件/软件级别的过程。
这是完全不同的两件事,我们无法比较。但是这些术语非常适合教给初学者编程语言是如何工作的。
Java JIT编译器的工作原理