编译器与解释器的根本区别是什么? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
zxgngl
V2EX    程序员

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

  •  
  •   zxgngl 2016-01-31 20:36:27 +08:00 12203 次点击
    这是一个创建于 3609 天前的主题,其中的信息可能已经有所发展或是发改变。
    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
    % = 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     Solana     919 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 34ms UTC 20:27 PVG 04:27 LAX 12:27 JFK 15:27
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86