V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
zxgngl
V2EX  ›  程序员

编译器与解释器的根本区别是什么?

  •  
  •   zxgngl · 2016-01-31 20:36:27 +08:00 · 11429 次点击
    这是一个创建于 3198 天前的主题,其中的信息可能已经有所发展或是发生改变。
    30 条回复    2016-02-03 04:35:42 +08:00
    codeaqua
        1
    codeaqua  
       2016-01-31 20:55:08 +08:00   ❤️ 1
    编译器: 编译完就可以扔了,运行不依赖它;
    解释器: 你要运行,必须依赖它;
    zhuangzhuang1988
        2
    zhuangzhuang1988  
       2016-01-31 21:47:56 +08:00
    扯啥本质。。 浪费时间。。
    donge
        3
    donge  
       2016-01-31 22:00:34 +08:00
    yuechen323
        4
    yuechen323  
       2016-01-31 22:47:52 +08:00 via iPhone
    根本区别是 运行时候,解释型需要将程序解释成机器懂的机器码来运行 费了一道手 而编译型在运行之前就已经让编译器给程序编译成机器码了 所以更快 如 c cpp
    Lab
        5
    Lab  
       2016-01-31 23:08:55 +08:00
    编译器:在代码运行之前,生成目标平台指令,可脱离编译器而独立运行。
    解释器:在代码运行过程中,生成目标平台指令,不可脱离解释器,无法独立运行。

    编译器: C 、 C++等
    解释器: Python 、 Ruby 、 PHP 等。
    seeker
        6
    seeker  
       2016-01-31 23:28:50 +08:00
    有没有 runtime 的区别
    lightening
        7
    lightening  
       2016-02-01 00:15:13 +08:00 via iPad
    @yuechen323 那 java 编译器算啥?
    fy
        8
    fy  
       2016-02-01 01:41:07 +08:00
    @Lab 动态语言中其实界限很模糊。

    java 分编译器和 VM ,会编译出二进制文件
    python 也是编译成字节码,有 VM ,有时候会输出为 pyc
    lua 同样是编译 + VM 执行

    然而这些都并没有什么卵用
    dorentus
        9
    dorentus  
       2016-02-01 01:58:20 +08:00 via iPhone
    榨汁机和电饭锅的本质区别是啥?
    MiguelValentine
        10
    MiguelValentine  
       2016-02-01 02:09:49 +08:00
    编译器是工具 解释器是环境
    neoblackcap
        11
    neoblackcap  
       2016-02-01 03:44:19 +08:00
    @lightening Java 就是编译型的,跟 C/C++之类的没区别,只不过一个是输出 x86/arm 平台的本地二进制代码,一个是输出可以运行在符合 JVM 标准的虚拟机字节码而已。
    pynix
        12
    pynix  
       2016-02-01 03:48:11 +08:00
    现在的 VM 基本都有 jit 了。
    lightening
        13
    lightening  
       2016-02-01 04:32:18 +08:00 via iPad
    @neoblackcap 那么它也不符合编译后可以独立运行这条
    minsheng
        14
    minsheng  
       2016-02-01 06:22:46 +08:00   ❤️ 1
    可以把解释器分成两种,一种是基于语法树的解释器,一种是基于字节码的解释器。

    举个例子, 3+4*5 ,基于语法树的解释器大概会是这样的:
    data Expr = Lit Integer | Add Expr Expr | Mul Expr Expr

    -- 构造语法树
    ast :: Expr
    ast = Add (Lit 3) (Mul (Lit 4) (Lit 5))

    -- 解释器,使用模式匹配
    eval :: Expr -> Int
    eval (Lit x) = x
    eval (Add e1 e2) = eval e1 + eval e2
    eval (Mul e1 e2) = eval e1 * eval e2

    而基于字节码的则会先把源代码翻译成一段字节码:
    % 0 = 3
    %1 = 4
    %2 = 5
    %3 = mul i32 %1, %2
    %4 = add i32 %0, %3

    上述代码为 LLVM 中间表示,每个 %x 代表一个虚拟寄存器,有无数个虚拟寄存器。解释器会先把这段代码翻译成只使用一定数量的寄存器的形式,比如说:
    %0 = 4
    %1 = 5
    %0 = mul i32 %0 %1
    %1 = 3
    %0 = add i32 %01 %1

    这里只用了两个寄存器。接着,就可以解释执行这段代码。

    另一种做法就是基于栈的解释器,大概长这样:
    push 3
    push 4
    push 5
    mul ;此时栈顶是 4 与 5
    add ;此时栈顶是 3 与 20

    据说这种方法实现起来比较简单,但是没有基于寄存器的解释方法来得快。如果没有记错的话, Lua 就是基于寄存器的解释,而 JVM 则很长一段时间都基于栈。

    所谓的编译器,无非就是只完成了到字节码的翻译步骤,将执行交给硬件完成。不过编译器这个概念依然没有意义,因为硬件也是可以模拟的,比如说 Bochs ,比如说 QEMU 。难不成我们把 GCC 编译出来的代码换个环境之行,它就变成了解释器了?同理, JVM 也可以用硬件实现。我认为,只要记得基于语法树的解释和基于字节码的解释这一区别即可。
    Perry
        15
    Perry  
       2016-02-01 06:59:54 +08:00 via iPhone
    上一下 Computer Architecture 就能理解了吧
    forrestchang
        16
    forrestchang  
       2016-02-01 07:44:05 +08:00
    可以看一下《程序设计语言——实践之路》这本书的第一章。

    R 大的这篇文章也可以参考一下: http://rednaxelafx.iteye.com/blog/492667
    gzxultra
        17
    gzxultra  
       2016-02-01 08:35:50 +08:00
    @Perry 体系结构并不讲这个啊
    Perry
        18
    Perry  
       2016-02-01 08:52:59 +08:00 via iPhone
    @gzxultra 看错了 还以为是问 compiler 和 assembler 的区别
    hazard
        19
    hazard  
       2016-02-01 09:46:48 +08:00
    offline 和 online 的区别
    airqj
        20
    airqj  
       2016-02-01 10:10:40 +08:00 via Android
    你是想不管冷热为省时间一次性穿好衣服,还是冷的时候穿热的时候脱?
    tiancaiamao
        21
    tiancaiamao  
       2016-02-01 12:08:13 +08:00
    推荐 《 Lisp in Small Pieces 》
    louk78
        22
    louk78  
       2016-02-01 14:58:57 +08:00
    编译器是将高级语言翻译为二进制文件
    解释器是将 PE 二进制翻译为机器指令
    rainex
        23
    rainex  
       2016-02-01 18:19:56 +08:00
    编译器:源代码->中间代码-> [可执行代码] ->操作系统载入自己执行

    解释器分两种:
    第一种:源代码-> [中间代码] ->操作系统载入解释器执行
    第二种:源代码->操作系统载入解释器执行

    也有把第二种解释器算作编译的, C#、 Java 乃至 zend 跑的 php 都类似的机制,但本质上还是一种解释执行。
    twd2
        24
    twd2  
       2016-02-01 19:19:55 +08:00
    编译器就是把源代码一起都翻译成机器看得懂的语言,然后这一坨交给机器来运行。

    解释器就是读取一段源代码,翻译成机器看得懂的语言,让机器执行,然后再处理下一段......
    rainex
        25
    rainex  
       2016-02-01 20:04:35 +08:00
    修正 23 楼:

    编译器:源代码->中间代码-> [可执行代码] ->操作系统载入自己执行

    解释器分两种:
    第一种:源代码-> [中间代码] ->操作系统载入解释器执行
    第二种:源代码->操作系统载入解释器执行

    也有把 [第一种] 解释器算作编译的, C#、 Java 乃至 zend 跑的 php 都类似的机制,但本质上还是一种解释执行。


    ps :不能修改的 bbs ,嗯
    jybox
        26
    jybox  
       2016-02-01 20:32:46 +08:00
    我现在觉得可能编译执行和解释执行是一个程度问题,取决于语言的设计和实现上,在编译阶段和运行阶段之间建立了多么强的抽象或隔离。
    FlowMEMO
        27
    FlowMEMO  
       2016-02-01 21:09:40 +08:00
    Engineering a Compiler 书中的说法是“ An interpreter takes as input an executable specification and
    produces as output the result of executing the specification.”,重要的是产生结果。

    书中举例将 PostScript 转换成图像的东西是解释器。从这个角度来看,给定 html 和 css ,浏览器的排版过程也可以看作是解释。
    libook
        28
    libook  
       2016-02-01 23:36:38 +08:00
    我上学的时候理解的是:编译器就是把源代码转换成机器码的软件,运行的时候直接运行机器码就可以了,不再依赖编译器;解释器就是一个懂得源代码的软件,运行这个软件然后直接让它按照源代码做事,每一个源代码指令编译器都懂得是什么具体的操作,并能立即执行。
    如果拿人来做比喻,就是:小 A 跟编译器说想吃螃蟹,于是编译器教会了小 A 如何剥螃蟹;小 B 跟解释器说他也想吃螃蟹,解释器就帮他剥好了螃蟹。这大概就是编译器和解释器的区别吧。
    当然实际的编译器和解释器的原理比这要复杂得多,你若真想究其毫厘还是要专门拿几个编译器和解释器来研究一下。
    cs202
        29
    cs202  
       2016-02-02 07:09:30 +08:00
    zxgngl
        30
    zxgngl  
    OP
       2016-02-03 04:35:42 +08:00
    编译是“转换变换”;解释是“赋予意思”。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1476 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 17:18 · PVG 01:18 · LAX 10:18 · JFK 13:18
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.