本文是我从另外一篇博客里拆分出来的,不然那篇博客结构不太好。
什么是可执行程序
从构成上来说,可执行程序是由机器可以识别执行的机器语言(也就是一堆 1 和 0)组成的程序。
从功能上来说,它可以将输入的内容按特定方式处理,然后再输出结果。
从文件格式上来说,Windows 中现在主流的可执行程序的格式是 PE(Portable Executable File Format),而其中的“Executable”缩写就是很多人熟知的 EXE;在 macOS 中,可执行程序被称为Mach-O executable file
。
解释器
在介绍脚本之前,需要了解一下“解释器”(有的地方叫做“解释程序”),以及其和编译器的区别
解释程序是会根据源程序和用户输入来进行处理,再输出处理后的结果。最经典的解释程序就是各种 Shell,比如 bash、zsh 等,源程序也就是指和解释程序对应脚本语言编写的脚本,他们只由解释程序处理,不会进行编译。
解释器和编译器的区别
解释程序和编译器经常被放在一起比较是因为,二者都是为了让用户可以输入,并且得到处理后的结果。只不过解释程序自己就可以接受输入、处理并输出结果,而编译器最终会生成一个可执行程序,然后由这个可执行程序接受输入、处理并输出结果。
一般编译器能带来更快的速度,解释程序能带来更好的错误信息诊断。更好的错误信息诊断的因为解释程序是一个部分一个部分的运行下去的,所以返回错误信息可以精确到行,甚至是列,而编译器经常只是告诉你哪个文件有问题。
不过现在的汇编器(不是指工具组)也可以做到很好的错误信息诊断,如果使用一些工具或者 IDE 甚至可以做到脚本随时打断点的地步,所以脚本好处一般只有方便(或许一些考试还会用到“更好的错误信息诊断”)。
关于脚本还有一些内容在下面的“为什么脚本不算可执行程序”部分,区分脚本和可执行程序是理解编译器中重要的一点。比如说 Java 是二者的混合体,哪部分是编译器,哪部分是解释程序呢?
什么是脚本
其实上文就提到了什么脚本:脚本就是解释程序能接受执行的代码。不同解释程序能接受执行的代码就是不同的脚本语言。
脚本语言编写的是一种输入内容,然后让解释程序去处理输入的内容,按照输入的内容进行操作,输入内容也不会转换成机器可以识别的内容。
比如下面这个 bash 语言的脚本,用来编译 C 语言程序、然后运行,最后删除生成的可执行程序。
#!/bin/bash
cc $1
./a.out
rm a.out
这个脚本会生成一个可执行程序,但是这个可执行程序是脚本生成的吗?不是,是脚本调用cc
这个程序去生成的,删除也是调用rm
这个程序来进行删除。
关于脚本有个很有意思的观点:
有些人认为写脚本不算编程,就是因为脚本并没有编译器进行编译,而是直接由解释程序执行的。
可执行程序和脚本的区别
在阅读上文之后,你会发现经常说的“编程”、“写程序”其实并不只是指 C 等语言编译后得到的程序,也包括写脚本。
二者其实都是可执行程序。
首先,二者都需要运行权限,只是执行主体不一样:前者是机器,后者是解释程序。
那么为什么二者都是程序呢?
这里来学一点英文:“程序”这个词别看你熟悉的不能再熟悉,但是你能试着用语言解释它吗?这个词在英文字典中的意思有很多,这里列出两个需要区分的:
a complete plan for solving a problem by the use of a mechanism (such as a computer)
可以插入机制(如计算机)的编码指令序列
a complete plan for solving a problem by the use of a mechanism (such as a computer) that includes both instructions to be inserted into the mechanism and plans for human activities such as interpreting output
通过使用机制(如计算机)解决问题的完整计划,该机制包括插入机制的指令和解释输出等人类活动计划
第一种解释就是经常说到的“应用程序”中“程序”的含义;第二种解释很少见,感觉很难理解,但是它其实就是“应急处理程序”中“程序”的含义,也就是一套流程,计算机中的“程序”只是其中之一。
所以脚本语言编写的东西也叫做程序(program),对应着上面第二个解释,当然这里的“program”翻译成“流程”可能更合适一点。现在也用了另一个名词,也更能区分二者,这个名词就是“脚本(script)”。在计算机科学史上,很多名词都是换来换去,最后因为一些机缘巧合现在才叫这个。
也就是说,现在经过编译形成可执行程序就叫做“可执行文件”,如果是由解释程序执行的就叫“脚本”。
希望能帮到有需要的人~