计算机编程语言:编译型与解释型区别
原文地址:https://blog.csdn.net/danpi1hao/article/details/64121610
计算机编程语言种类非常多,根据与计算机硬件的贴近程度和抽象程度大致可分为3类,自顶向下分别是
高级语言(抽象层次更高的便于记忆和表示的英文代码)
|
汇编语言(抽象层次较高的对应机器硬件的cpu指令集,英文缩的助记符号代码)
|
机器语言(抽像层次最低的由0、1序列所表示的机器码)
众所周知,计算机底层只能识别(并执行)0、1序列的机器码,这表示所有的高级编程语言所编写的代码,最终都要以某种方式被转换成能被计算机识别的0、1序列机器码,方可被计算机接受并执行。这种将代码转换为机器码的方式可分为编译型和解释型这2类:
编译型:运行前先由编译器将高级语言代码编译为对应机器的cpu汇编指令集,再由汇编器汇编为目标机器码,生成可执行文件,然最后运行生成的可执行文件。最典型的代表语言为C/C++,一般生成的可执行文件及.exe文件。
解释型:在运行时由翻译器将高级语言代码翻译成易于执行的中间代码,并由解释器(例如浏览器、虚拟机)逐一将该中间代码解释成机器码并执行(可看做是将编译、运行合二为一了)。最典型的代表语言为JavaScript、Python、Ruby和Perl等
两种方式的异同之处:
(1) 转换为机器码的时机和运行效率
两种转换为机器码的方式,最大不同之处是处理转换为机器码的时机不同。编译型是在运行前(且只编译一次),需要做转换工作,并生成一个可执行的机器码文件,用户每次运行该可执行文件执行即可,效率、执行速度要比解释型的快。因为解释型是在运行时做转换工作,并不生成可执行文件,所以每次运行都需要做一下转换工作,然后再执行,效率自然就低了。
(2) 纠错排查
编译型语言,在编译阶段即可发现常见的语法或者链接等错误,此机制可在运行前帮助程序员排查出可能潜在的语法、语义和类型转换错误,编译型语言一般都有明确的变量类型检测,也被称作强类型语言,即编译型语言至少能确保所生成的可执行文件肯定是可运行的,至于执行的逻辑不对则属于程序员业务逻辑错误范畴了。
而对于解释型语言,代码中的错误必须直到运行阶段方可发现,由此造成的困惑是:往往一段程序看不出问题但却在运行阶段错误连连且需要一个个排查:变量拼写错误、方法不存在等。但也正是基于解释是在运行期执行转化的特性,一般的解释型语言通常都有自己的shell,可以在不确定某些执行结果是立即“动手执行”试一下,这就比每次都需要编译后才能运行并看到结果省去不少时间,鱼和熊掌不可兼得的理念再一次被验证了。
(3) 可移植性
编译型在编译后生成的可执行文件,是相对与本机机器指令集的,所生成的可执行文件移植到不同机器指令集的机器上,势必不一定能正常运行。而解释型的,尽管在不同配置的机器上,也是最终会解释成基于当前机器指令集的机器码并执行,故解释型的可移植性相对来说还是强于编译型的。
(4) 适用性
从第(1) 点我们知道编译型执行速度较解释型快,因为编译型会把大量时间花在编译上,所以对机器和跨平台性的要求不高,开发操作系统、大型应用程序、数据库程序系统时一般都采用编译型语言;而解释型由于每次运行都需要解释一遍,对机器有一定的配置要求(在内存较小的机器上去一遍遍解释执行肯定是件很痛苦的事),适用的地方是一些例如网页脚本、服务器脚本及辅助开发接口这类对机器配置要求不高、需要一定跨平台兼容性的程序。
鱼和熊掌可兼得吗?
综上所述,既然编译型与解释型各有优缺点又相互对立,所以一些语言都有把两者折衷起来的趋势:
Java为了实现跨平台的特性,专门在从高级语言代码转换至机器码过程的中间加入了一层中间层JVM(java虚拟机),Java首先依赖编译器将代码(.java)编译成JVM能识别的字节码文件(.class),然后由JVM解释并执行改字节码,也可结合JIT(即时编译)技术,将解释生成的机器码转换为更高效的本地机器码,且该机器码可被缓存,来提高重复执行的效率。这样的结合,令程序员在使用Java时即可享受编译带来的强类型编译检查的好处,又能在执行时享受代码执行的高效性和跨平台性,何乐而不为呢?
Python是解释型语言,但为了效率上的考虑,也提供了编译方式,编译后生成的也是字节码的文件形式,并由Python的的VM(虚拟机)的去执行,这点可以说和Java的编译执行方式类似。不同点在于,Python的编译并非强制执行的操作,确切来说Python的编译是自动的,通常发生在对某个模块(module)的调用过程中,编译成字节码的可以节省加载模块的时间,以此达到提高效率的目的。可见,某些先进的高级语言在对编译和解释方面的拿捏舍去,都采取了一种:两手抓,两手都要硬的态度哦:)