C语言学习
编译型语言与解释型语言
编译型语言和解释型语言本质上是源代码执行方式的不同,主要区别在于源代码如何转换成计算机能运行的机器码。
我们编写的源代码是人类语言,人类能够理解;但是对于计算机硬件(CPU),它无法读懂源码,根本无法执行,计算机只能识别某些特定的二进制指令,所以在程序真正运行之前必须将源代码转换成二进制指令,所谓二进制指令,也就是机器码,是 CPU 能够识别的硬件层面的“代码”。
编译型语言,如C、C++、Go、Rust、Swift
用专用的编译器,针对特定的操作平台(操作系统)将某种高级语言的源代码一次性翻译成可被硬件平台直接运行的二进制机器码(编译);编译好的可执行性文件(.exe),可在相对应的平台上运行(移植性差,但运行效率高)。编译器本质也是一种程序
对于编译型语言,开发完成以后需要将所有的源代码都转换成可执行程序,比如 Windows 下的.exe文件,可执行程序里面包含的就是机器码。只要拥有可执行程序,就可以随时运行,不用再重新编译了,也就是“一次编译,无限次运行”。在运行的时候,不再需要源代码和编译器,所以说编译型语言可以脱离开发环境运行。
C 程序编译后的 .exe/ELF 程序是成品,可以直接分享给用户运行,不需要用户再编译。这也是许多软件厂商发布可执行文件而不是源代码的原因。
编译型语言一般是不能跨平台的,也就是不能在不同的操作系统之间随意切换。例如,不能将 Windows 下的可执行程序拿到 Linux 下使用,也不能将 Linux 下的可执行程序拿到 Mac OS 下使用(虽然它们都是类 Unix 系统)。另外,相同操作系统的不同版本之间也不一定兼容,例如不能将 x64 程序(Windows 64 位程序)拿到 x86 平台(Windows 32 位平台)下运行。但是反之一般可行,因为 64 位 Windows 对 32 位程序作了良好的兼容性处理。
一个大型的商业软件可能在不同平台下90%的源代码处理逻辑和算法都是相同的,但是有10%的专用代码是针对不同操作系统单独进行维护的,例如,在C语言中要想让程序暂停可以使用“睡眠”函数,在 Windows 平台下该函数是 Sleep(),在 Linux 平台下该函数是 sleep(),首字母大小写不同。其次,Sleep() 的参数是毫秒,sleep() 的参数是秒,单位也不一样。
| 系统 | 常用编译器 |
|---|---|
| Windows | MSVC、MinGW、Clang |
| Linux | gcc、clang |
| macOS | clang(默认) |
解释型语言,如Python、JavaScript、PHP、Ruby、Shell
解释型语言是使用解释器一边执行一边转换,用到些源代码就转换哪些,不会生成可执行程序。因为每次执行程序都需要重新转换源代码,所以解释型语言的执行效率天生就低于编译型语言,甚至存在数量级的差距。它不能脱离解释器运行,但跨平台比较容易,只需提供特定解释器即可。
还有许多语言既有编译也有解释的部分
✔️ Java
代码先编译成字节码(.class),再由 JVM 解释或 JIT(即时编译)执行。
✔️ JavaScript
现代 JS 引擎采用 JIT:解释 + 编译优化结合。
总结
对于编译型语言,我们下载到的是可执行文件,源代码被作者保留,所以编译型语言的程序一般是闭源的。
相比于编译型语言,解释型语言几乎都能跨平台,“一次编写,到处运行”是真实存在的,而且比比皆是。那为什么解释型语言就能跨平台呢?
这主要归功于解释器!
我们所说的跨平台,是指源代码跨平台,而不是解释器跨平台。解释器用来将源代码转换成机器码,本质上是一个可执行程序,是无法跨平台的。例如,Python 不是一个解释器跑遍所有平台,而是每个平台都有一个对应的解释器版本。
Windows → python.exe(编译为 PE 格式)
Linux → python(ELF 格式)
macOS → python(Mach-O 格式)
官方需要针对不同的平台开发不同的解释器,这些解释器必须要能够遵守同样的语法,识别同样的函数,完成同样的功能,只有这样,同样的代码在不同平台的执行结果才是相同的。所以,解释型语言之所以能够跨平台,是因为有了解释器这个中间层。在不同的平台下,解释器会将相同的源代码转换成不同的机器码,帮助我们屏蔽不同平台之间的差异。
| 类型 | 原理 | 优点 | 缺点 |
|---|---|---|---|
| 编译型语言 | 通过专门的编译器,将所有源代码一次性转换成特定平台(Windows、Linux 等)执行的机器码(以可执行文件的形式存在)。 | 编译一次后,脱离了编译器也可以运行,并且运行效率高。 | 可移植性差,不够灵活。 |
| 解释型语言 | 由专门的解释器,根据需要将部分源代码临时转换成特定平台的机器码。 | 跨平台性好,通过不同平台的解释器,将相同的源代码解释成不同平台下的机器码。 | 一边执行一边转换,效率较低。 |
细节Tips
整数/整数=整数,整数/浮点数=浮点数,浮点数/浮点数=浮点数,在整数与浮点数运算时,要明确输出结果是属于int还是float;



