【问题标题】:Compiler versus Interpreter编译器与解释器
【发布时间】:2012-04-15 11:16:37
【问题描述】:

那么,让我看看我是否明白这一点。

  1. 当我们说编译器和解释器之间的区别时,解释器将高级指令翻译成中间形式,然后执行。 [我认为编译器也将高级指令转换为中间形式,但此时它生成目标代码而不是执行它,对吧?]

  2. 解释器一次读取一条指令或一行的源代码,将此行转换为机器代码并执行。 [解释器本身不会将代码转换为机器代码,它使用自己的预编译函数来评估指令(在解析之后)。例如。高级语言中的 add 表达式将使用之前编译的解释器 add 函数进行评估,对吗?]

【问题讨论】:

  • 在1.第二次说“解释器”的地方,你的意思是“编译器”对吗?
  • 不,Eric,我是说翻译。

标签: architecture compiler-construction operating-system interpreter


【解决方案1】:

主要区别在于:解释器在运行源代码时对其进行处理。它不会将源代码转换为机器代码,它只是使用自己的代码来完成源代码的指示。编译器将源代码转换成可以直接运行的机器码。

并非所有编译器都与执行过程分开。例如,大多数 Java 运行时都包含一个“JIT 编译器”,它可以根据需要在 Java 代码运行时对其进行编译。

你可以有一些介于两者之间的东西。本质上,可以首先使用类似于编译的过程将源代码转换为更小且更易于解释的东西。然后可以解释这个编译的输出。 (例如,第一遍可以转换,比如 'if' 到 53,'else' 到 54,'for' 到 55,等等 - 这将使解释器不必处理代码中的可变长度字符串实际上并不处理字符串。)

【讨论】:

    【解决方案2】:

    我同意第一个,尽管解释器一次只处理一行并不一定是真的(它可以根据对整个代码的了解进行优化)。

    我认为第二个有点不对劲:编译器确实创建了“机器码”(对于 JVM,它可能是字节码)。解释器根据输入执行自己程序的一部分(到目前为止与编译器相同),这些执行的部分正在执行输入中描述的计算(而不是执行计算以计算所需的机器代码)。

    可能会模糊两者之间的界限,因为编译器可以生成将在执行时解释的代码(根据编译时不可用的因素提供运行时优化)

    【讨论】:

    • 您好 Attila,如果我理解正确,您是否同意我关于第 2 点的看法?
    • 不完全正确:粗体部分不正确:解释器(主动)未完成对执行代码的翻译:编译解释器时已完成(假设它本身没有被解释:))。解释器使用其现有代码(已经是机器代码)来执行所需的计算。这基本上就是括号 ([]) 中的内容,但不是粗体部分所说的内容
    • 粗体部分不是我写的,我在某处读过。我只是强调它,因为我不同意它。我的话只是括号中的内容。因此,您真的同意我的观点:D
    【解决方案3】:

    关于 (1),你是对的。

    Ad (2),解释器不需要一次读取一条指令的源代码,因为在解释包含循环的代码时这太昂贵了。更有可能的是,它读取整个表达式、语句、函数甚至源文件,将它们转换为中间格式并对其进行评估。

    请注意,无论是编译器还是解释器都不需要在任何时候生成机器码;许多编程语言,包括 Java、Python,以及像 Prolog 这样的旧语言,通常都被编译为虚拟机字节码。在 Python 和 Prolog 中,“解释器”通常是字节码编译器/字节码解释器的组合。

    我所知道的关于编译和解释的最好的介绍是SICP 的第 4 章和第 5 章,它们从讨论一个非常简单的解释器开始,然后迭代地改进它,直到它成为一个成熟的编译器。

    【讨论】:

    • 嗨 larsman,但是当我们使用 gcc 时,它确实会生成机器码,对吧?
    • @user1334379:是的,GCC 产生机器代码,所有主要的 C 和 C++ 编译器也是如此。有趣的是,GCC 的 Java 编译器 GCJ 也可以产生机器码,这与其他 Java 编译器不同。
    【解决方案4】:

    什么是翻译?

    S -> T 翻译器接受以源语言 S 表达的代码,并将其翻译成以另一种(目标)语言 T 表达的等效代码。

    翻译示例:

    • 编译器 - 将高级代码转换为低级代码,即 Java -> JVM
    • 汇编程序 - 将汇编语言代码翻译成机器代码,即 x86as -> x86
    • 高级翻译器 - 将代码从一个 PL 翻译成另一个,即 Java -> C
    • 反编译器 - 将低级代码转换为高级代码,即 JVM -> Java

    什么是口译员?

    S 解释器 接受用语言 S 表达的代码,并立即执行该代码。它通过一次获取、分析和执行一条指令来工作。

    当用户以交互方式输入指令(想想 Python)并希望在输入下一条指令之前获得输出时非常棒。当程序只执行一次或需要可移植时也很有用。

    • 解释程序比执行本机机器代码慢得多
      • 解释高级语言的速度要慢约 100 倍
      • 解释中级(例如 JVM 代码)语言的速度要慢约 10 倍
    • 如果一条指令被重复调用,就会被重复分析——很费时间!
    • 无需编译代码

    区别

    行为

    • 编译器将源代码转换为机器代码,但不执行源代码或目标代码。
    • 解释器一次执行一条指令源代码,但不翻译源代码。

    性能

    • 编译器需要相当长的时间将源程序翻译成本机机器码,但后续执行速度很快
    • 解释器立即开始执行源程序,但执行速度很慢

    解释性编译器

    解释性编译器是编译器和解释器之间的良好折衷。它将源程序翻译成虚拟机代码,然后进行解释。

    解释性编译器将快速翻译与适度快速执行相结合,前提是:

    • VM 代码低于源语言,但高于本机机器代码
    • VM 指令具有简单的格式(可以由解释器快速分析)

    示例:JDK 为 Java 提供了解释性编译器


    Source

    【讨论】:

      猜你喜欢
      • 2011-03-11
      • 1970-01-01
      • 2011-01-11
      • 1970-01-01
      • 2011-07-01
      • 1970-01-01
      • 2018-10-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多