编译器简介

为啥需要编译器?

电脑,手机,嵌入式产品的处理器芯片,软件在上面运行的原理是0101二进制码组成的指令集;例如我们的应用是计算两个数的和,我们的程序如果用C++编写可能如下所示:

int sum(int a, int b)
{
    return a + b;
}

在机器的世界里,只有电平信号,对应的逻辑值只有0与1二进制值,所以上面的文本能够被硬件执行,需要转换,这个过程就是编译器的工作,我们来看在x86硬件平台,GCC编译转换的结果可能如下所示:

_Z3sumii:
 -> 55
 push   rbp
 -> 48 89 e5
 mov    rbp,rsp
 -> 89 7d fc
 mov    DWORD PTR [rbp-0x4],edi
 -> 89 75 f8
 mov    DWORD PTR [rbp-0x8],esi
 -> 8b 55 fc
 mov    edx,DWORD PTR [rbp-0x4]
 -> 8b 45 f8
 mov    eax,DWORD PTR [rbp-0x8]
 -> 01 d0
 add    eax,edx
 -> 5d
 pop    rbp
 -> c3
 ret

这是一段汇编代码及其对应的机制码的表现形式,请忽略任何尚且不了解的内容,在此,只想表达我们的求和运算转换成机器指令必然会用到类似于图示的add    eax,edx,而它对应的机器指令即01 d0,也就是通俗的理解,01 d0这两个字节会被机制执行求和运算,这里只是通俗的理解,请忽略不完全正确的解释~

一定需要编译器吗?

即使简单使用过Python语言的朋友,也会有疑问,在使用Python写一个简单的程序似乎没有使用编译器的过程,甚至于中间的任何转换都没有发生?是的,在忽略小众的知识点的前提下,通俗的我们可以把语言分成编译型语言和解释型语言,前面我们的例子使用的C++(以及其他的语言如C,Objective-C等)语言就是编译型语言,即需要编译器进行编译转换成机器码才能运行;而Python(以及其他的语言如Perl,Shell脚本,Matlab等)语言是解释型语言,那么解释型语言的工作模型是怎样的,是如何运行的?

解释型语言通常有一个解释器程序,这个程序可以读取并且解释我们使用Python语言开发的文本的内容,示例如下:

def add(a, b):
    return a + b

result = add(3, 5)
print(result)

当python script.py运行这个代码文件的时候,解释器会先读取代码文件中这段代码内容,解释器将代码分解为词法单元,并检查语法是否正确,接下来解释器会将代码转换成一种中间形式,称为字节码,存储在.pyc文件中(通常位于__pycache__目录下);上面程序可能的字节码示例如下:

LOAD_CONST   0 ()
MAKE_FUNCTION 0
STORE_NAME   0 (add)
LOAD_NAME    0 (add)
LOAD_CONST   1 (3)
LOAD_CONST   2 (5)
CALL_FUNCTION 2
STORE_NAME   1 (result)
LOAD_NAME    2 (print)
LOAD_NAME    1 (result)
CALL_FUNCTION 1

解释器会逐行读取并且执行对应的字节码;换句通俗的话来讲,解释器知道程序是想进行add操作,于是解释器就执行了add的操作,解释器知道程序是想进行print操作,于是执行了底层相关的io输出的操作,如果我们再粗糙一点理解,就是我们告诉解释器去干什么,解释器便帮助我们去做了什么事情;而编译型语言是我们自己编写的代码,通过编译器直接编译成最底层指令,没有一个中间助手。

既然解释器是一个可执行的程序,能够进行底层的操作,所以解释器是一个被编译的程序(比如CPython,Python官方实现,使用 C 语言编写的解释器),所以如果一定要从本质上来讲,Python代码想在机器硬件上执行,底层一定也是指令集,同样离不开编译,离不开编译器,只不过这个过程发生在Python解释器上面,是由提供解释器的开发完成的。

从上面的对比,可以看出,解释型语言语法层面可能更简单更易理解,能够跨平台使用,因为不同的平台有不同的解释器,解释器不同适配底层硬件机器码,上层开发者写的Python代码可以共用,但由于运行时需要解释,运行效率相对会低一些,具体取决于实际应用场景;而编译型语言,同样的代码,如果想运行在不同的平台,比如电脑的x86处理器架构,嵌入式处理Power PC架构,ARM处理器aarch64架构等,不同的操作系统,比如Windows,Ubuntu等需要用不同的编译器进行重新编译,生成对应平台下的可执行文件,但由于编译后是直接机器指令,所以运行效率较高。

总结:解释型语言可以不需要编译器,或者至少对于使用这种语言的开发者而言不需要特别关心这件事情,解释器会负责完成相关的内容,解释器在安装解释型语言开发环境的时候会被安装,直接使用即可。关于解释器相关的这些内容与本文章无关,现在你可以忽略上面的这些内容了~~~

C/C++编译器有哪些?

本文章接下来以C/C++语言为背景语言编写各种示例,我们来看一下C/C++语言有哪些对应的编译器。按照前面的介绍,不同的平台下对应的编译器是不同的,举例如下:

比如在x86平台上有大名鼎鼎的GCC编译器,Clang/LLVM,大家熟知的Windows平台上的MSVC(Microsoft Visual C++),GNU提供的Windows版本上的GCC MinGW(Minimalist GNU for Windows),Cygwin;

ARM硬件平台上,也有大名鼎鼎的Arm GNU Toolchain编译器工具链,在QNX操作系统下,有对应的QCC编译器;

对于嵌入式MCU处理器,比如瑞萨处理RH850,RL78等,有瑞萨公司提供的专门用于其对应指令集的编译器,如CC-RH;比如在意法半导体STM32F107芯片(ARM Cortex-M架构)上开发,可以使用集成的开发环境IAR C/C++ Compiler(ICCARM)或者KEIL MDK下的ARM Compiler;再比如在Freescale Power PC架构的处理器MPC5604上有CodeWarrior集成开发环境下提供的编译器;

同时,对于嵌入式处理器,有些专门的编译器公司提供专业级的编译器,能够支持多种芯片平台和架构,如GHS GreenHills,TASKING,HighTec等大名鼎鼎的编译器;

好了,这里我们只是简单的随意列举了一些平台下常见的编译器,简单了解就好,阅后请忽略~~~

专栏主题

本专栏“有趣的编译器”发布在x86平台,Linux Ubuntu20.04操作系统下GCC编译器相关的知识体系,虽然不同编译器的编译选项,命令行参数,语言支持上不尽相同,甚至区别明显,但本质大同小异,希望通过本专栏,能够帮助初学者,或者想提高的伙伴们学到一些更深入更本质的内容,能够在自己的领域接触到不同的编译器时运筹帷幄,游刃有余!

你可能感兴趣的:(有趣的编译器,c++)