编译语言与口译语言

2020/10/29 14:51 · python ·  · 0评论

我正在尝试更好地理解它们之间的区别。我在网上找到了很多解释,但是它们倾向于抽象的差异,而不是实际的含义。

我的大部分编程经验都来自CPython(动态的,解释的)和Java(静态的,编译的)。但是,我知道还有其他种类的解释和编译语言。除了可以从以编译语言编写的程序中分发可执行文件这一事实之外,每种类型是否都有优点/缺点?通常,我听到人们争辩说解释语言可以交互使用,但是我相信编译语言也可以具有交互实现,对吗?

编译语言是一种程序,一旦编译,该程序就会在目标计算机的指令中表示出来。例如,源代码中的加号“ +”操作可以直接转换为机器代码中的“ ADD”指令。

一种解释语言是其中所述指令不被目标机器直接执行,而是读取和执行通过一些其它方案(其通常写入本机机器的语言)。例如,解释器将在运行时识别相同的“ +”操作,然后使用适当的参数调用其自己的“ add(a,b)”函数,然后执行机器代码“ ADD”指令。

您可以使用解释语言或编译语言来做任何事情,反之亦然-它们都是图灵完整的。然而,两者在实现和使用上都有优点和缺点。

我将完全概括(纯粹主义者请原谅!),但是,大致而言,这是编译语言的优点:

  • 通过直接使用目标计算机的本机代码来提高性能
  • 有机会在编译阶段进行强大的优化

以下是解释语言的优点:

  • 易于实现(编写好的编译器非常困难!)
  • 无需运行编译阶段:可以直接“即时”执行代码
  • 可以更方便地使用动态语言

请注意,诸如字节码编译之类的现代技术增加了一些额外的复杂性-此处发生的是,编译器针对的是与底层硬件不同的“虚拟机”。然后可以在以后的阶段再次编译这些虚拟机指令,以获取本机代码(例如,由Java JVM JIT编译器完成)。

语言本身既不会编译也不会解释,而仅是语言的特定实现。Java是一个完美的例子。有一个基于字节码的平台(JVM),一个本机编译器(gcj)和一个Java超集的插入器(bsh)。那么,Java现在是什么?字节码编译,本机编译还是解释?

Scala,Haskell或Ocaml是经过编译和解释的其他语言。这些语言中的每一种都有一个交互式解释器,以及用于字节码或本机代码的编译器。

因此,通常通过“编译”和“解释”对语言进行分类没有多大意义。

从以下方面开始思考:过去的爆炸

很久很久以前,曾经有计算解释器和编译器。各种大惊小怪的结果使一个人的优胜劣汰。普遍的观点在当时是沿着线的东西:

  • 口译员:快速开发(编辑和运行)。执行速度很慢,因为每个语句每次执行时都必须被解释为机器代码(想想这对于执行数千次循环意味着什么)。
  • 编译器:开发缓慢(编辑,编译,链接和运行。编译/链接步骤可能需要花费大量时间)。快速执行。整个程序已经在本机代码中。

在解释的程序和已编译的程序之间存在一个或两个数量级的运行时性能差异。其他区别点,例如代码的运行时可变性,也引起了一些关注,但主要区别围绕着运行时性能问题。

如今,景观已发展到某种程度,以至于汇编/解释的区别几乎是无关紧要的。许多编译语言要求运行时服务不是完全基于机器代码的。同样,大多数解释语言在执行之前都会被“编译”为字节码。字节码解释器可能非常高效,并且从执行速度的角度来看,可以与某些编译器生成的代码相媲美。

经典的区别是,编译器使用某种运行时系统即时生成本机代码,解释器即时读取源代码并生成机器代码。如今,几乎没有经典的解释器了-几乎所有经典的解释器都编译成字节码(或其他半编译状态),然后在虚拟“机器”上运行。

极端简单的情况:

  • 编译器将生成目标计算机的本机可执行文件格式的二进制可执行文件。该二进制文件包含除系统库以外的所有必需资源。它无需任何进一步的准备和处理即可运行,并且像闪电一样运行,因为该代码是目标计算机上CPU的本机代码。

  • 解释器将在循环中向用户显示提示,让他可以输入语句或代码,并且在命中RUN或等效命令时,解释器将检查,扫描,解析并以解释方式执行每一行,直到程序运行至停止点或错误为止。因为每一行都是独立处理的,并且解释器不会从以前看过该行中“学到”任何东西,所以每行每次都需要将人类可读语言转换为机器指令,所以这很慢。从好的方面来说,用户可以通过各种方式检查程序并与之交互:更改变量,更改代码,在跟踪或调试模式下运行...等等。

有了这些,我让我解释一下生活不再那么简单了。例如,

  • 许多解释器会预编译给出的代码,因此不必一次又一次地重复翻译步骤。
  • 一些编译器不编译为特定于CPU的机器指令,而是编译为字节码,这是一种虚拟机器的人造机器代码。这使编译后的程序更具可移植性,但是在每个目标系统上都需要一个字节码解释器。
  • 字节码解释器(我在这里看着Java)最近趋向于在执行之前重新编译它们为目标部分的CPU获得的字节码(称为JIT)。为了节省时间,通常只对经常运行的代码(热点)执行此操作。
  • 一些看起来和行为像解释器的系统(例如,Clojure)会立即编译它们获得的任何代码,但允许以交互方式访问程序环境。从根本上来说,这就是二进制编译器为解释器带来的便利。
  • 一些编译器并没有真正编译,只是预消化并压缩代码。不久前,我听说Perl是这样工作的。因此,有时编译器只是在做一些工作,而且大部分仍在解释中。

最后,这些天来,解释与编译是一个折衷,编译时所花费的时间(一次)通常会因更好的运行时性能而获得回报,但是解释性环境为交互提供了更多机会。编译与解释主要是关于如何“理解”程序的工作如何在不同的过程之间进行划分的问题,并且由于语言和产品试图同时兼顾两者的优势,因此如今的界限有些模糊。

来自http://www.quora.com/What-is-the-difference-between-compiled-and-interpreted-programming-languages

两者没有区别,因为“编译程序设计语言”和“解释程序设计语言”不是有意义的概念。任何编程语言(实际上是任何一种编程语言)都可以解释或编译。因此,解释和编译是实现技术,而不是语言的属性。

解释是一种技术,通过该技术,另一个程序(解释器)代表正在解释的程序执行操作以使其运行。如果您可以想象阅读程序并按照程序说的做一步一步,例如在草稿纸上说,那也正是解释器的工作。解释程序的常见原因是解释器相对容易编写。另一个原因是,解释器可以监视程序在运行时试图执行的操作,以执行安全性策略。

编译是一种技术,通过该技术可以将用一种语言(“源语言”)编写的程序转换为另一种语言(“目标语言”)的程序,这希望与原始程序具有相同的含义。在进行翻译时,编译器通常还会尝试以使目标程序更快的方式(不改变其含义!)来尝试转换程序。编译程序的一个常见原因是,有一种很好的方法可以用目标语言快速运行程序,而无需一路解释源语言。

根据上述定义,您可能已经猜到这两种实现技术不是互斥的,甚至可能是互补的。传统上,编译器的目标语言是机器代码或类似的东西,它表示特定计算机CPU可以理解的任何数量的编程语言。然后,机器代码将“运行在金属上”(尽管如果看起来足够接近,人们可能会发现“金属”的工作原理很像解释器)。但是,如今,使用编译器生成要解释的目标代码非常普遍,例如,这就是Java过去(有时仍然如此)的工作方式。有些编译器会将其他语言翻译成JavaScript,然后通常在网络浏览器中运行,这些浏览器可能会解释JavaScript,或将其编译为虚拟机或本机代码。我们还提供了机器码解释器,可用于在另一种机器上模拟一种硬件。或者,可以使用编译器生成目标代码,然后将其作为另一编译器的源代码,后者甚至可以及时在内存中编译代码以使其运行,然后依次运行。你明白了。有很多方法可以组合这些概念。

与已编译的源代码相比,已解释的源代码的最大优势是PORTABILITY

如果源代码已编译,则需要为要在其上运行程序的每种类型的处理器和/或平台编译不同的可执行文件(例如,一种用于Windows x86,一种用于Windows x64,一种用于Linux x64,等等。上)。此外,除非您的代码完全符合标准且不使用任何平台特定的功能/库,否则您实际上将需要编写和维护多个代码库!

如果您的源代码被解释,则只需编写一次即可,并且可以在任何平台上由适当的解释器来解释和执行它!它是便携式的需要注意的是一个解释器本身是一个可执行程序编写和编译为特定平台。

编译代码的一个优点是,它向最终用户隐藏了源代码(可能是知识产权),因为您部署了晦涩的二进制可执行文件,而不是部署原始的人类可读源代码。

编译器和解释器完成相同的工作:将编程语言转换为另一种编程语言,通常更接近硬件,通常指导可执行的机器代码。

传统上,“编译”是指这种翻译一次完成,由开发人员完成,然后将生成的可执行文件分发给用户。纯粹的例子:C ++。编译通常会花费很长时间,并且会尝试进行大量昂贵的优化,以使生成的可执行文件运行得更快。最终用户没有工具和知识可以自己编译东西,并且可执行文件通常必须在各种硬件上运行,因此您不能进行许多针对硬件的优化。在开发过程中,单独的编译步骤意味着更长的反馈周期。

传统上,“已解释”是指当用户要运行程序时,翻译是“即时”进行的。纯示例:香草PHP。天真的解释器每次运行时都必须解析和翻译每段代码,这使其非常慢。它无法执行复杂且成本高昂的优化,因为它们所花费的时间比执行所节省的时间还要长。但是它可以充分利用其运行的硬件的功能。缺少单独的编译步骤可减少开发过程中的反馈时间。

但是如今,“编译与解释”已不是一个黑白问题,介于两者之间。天真的,简单的口译员已经绝迹了。许多语言使用两步过程,其中将高级代码转换为平台无关的字节码(解释起来更快)。然后,您便有了“及时编译器”,每个程序运行一次最多编译一次代码,有时缓存结果,甚至可以明智地决定解释很少运行的代码,并对运行频繁的代码进行强大的优化。在开发过程中,调试器甚至可以针对传统编译语言在正在运行的程序中切换代码。

首先,澄清一下,Java不是完全以C ++的方式静态编译和链接的。它被编译成字节码,然后由JVM解释。JVM可以即时对本机语言进行编译,但不必这样做。

更重要的是:我认为互动性是主要的实际差异。由于所有内容均已解释,因此您可以提取一小段代码,然后针对环境的当前状态进行解析和运行。因此,如果您已经执行了初始化变量的代码,则可以访问该变量,等等。它确实可以将其自身用于诸如功能样式之类的事情。

但是,解释会花费很多,尤其是当您拥有一个具有大量引用和上下文的大型系统时。根据定义,这是浪费的,因为相同的代码可能必须解释和优化两次(尽管大多数运行时对此都有一些缓存和优化)。尽管如此,您仍然需要支付运行时成本,并且经常需要运行时环境。您也不太可能看到复杂的过程间优化,因为目前它们的性能还不够互动。

因此,对于那些变化不大的大型系统,对于某些语言而言,预编译和预链接所有内容更有意义,请执行所有您可以做的优化。最终将获得非常精益的运行时,该运行时已针对目标计算机进行了优化。

至于生成可执行文件,与恕我直言无关。您通常可以使用编译语言创建可执行文件。但是,您也可以使用解释语言创建可执行文件,只是解释器和运行时已打包在可执行文件中,并且对您隐藏了。这意味着您通常仍需支付运行时成本(尽管我确信对于某些语言,有一些方法可以将所有内容转换为树可执行文件)。

我不同意所有语言都可以互动。某些语言(例如C)与机器和整个链接结构紧密相关,以至于我不确定您是否可以构建有意义的完整交互式版本

给出实际答案相当困难,因为区别在于语言定义本身。可以为每种编译语言构建解释器,但不可能为每种解释语言构建编译器。语言的形式定义非常重要。因此,理论上的信息学方面的东西在大学里就比较受人喜欢。

Python图书©2015 Imagine Publishing Ltd,仅通过第10页中提到的以下提示来区分差异:

一种解释性语言(例如Python)是一种将源代码转换为机器代码,然后在每次程序运行时执行的语言。这与诸如C之类的编译语言不同,后者仅将源代码转换为机器代码一次–每次程序运行时,都会执行所生成的机器代码。

编译是从以编译的编程语言编写的代码中创建可执行程序的过程。编译允许计算机运行和理解程序,而无需使用用于创建该程序的编程软件。编译程序时,通常是针对特定平台(例如IBM平台)编译的,该平台可与IBM兼容计算机一起使用,但不适用于其他平台(例如Apple平台)。第一个编译器是由Grace Hopper在哈佛Mark I计算机上开发的。如今,大多数高级语言都将包含其自己的编译器或可用的工具包,可用于编译程序。与Java一起使用的编译器的一个很好的例子是Eclipse,与C和C ++一起使用的编译器的一个例子是gcc命令。

简短(不精确)的定义:

编译语言:整个程序立即转换为机器代码,然后由CPU运行机器代码。

解释的语言:逐行读取程序,并在读取一行后立即由CPU执行该行的机器指令。

但是,实际上,如今很少有语言是纯粹编译或纯粹解释的,通常是混合的。有关图片的更详细描述,请参见以下线程:

编译和解释之间有什么区别?

或我后来的博客文章:

https://orangejuiceliberationfront.com/the-difference-between-compiler-and-interpreter/

本文地址:http://python.askforanswer.com/bianyiyuyanyukouyiyuyan.html
文章标签: ,   ,   ,   ,  
版权声明:本文为原创文章,版权归 admin 所有,欢迎分享本文,转载请保留出处!

文件下载

老薛主机终身7折优惠码boke112

上一篇:
下一篇:

评论已关闭!