[译]C++, Java和C#的编译过程解析
添加时间:2013-6-26 点击量:
1.1.1 择要
我们知道策画机不克不及直接懂得高等说话,它只能懂得机械说话,所以我们必必要把高等说话翻译成机械说话,如许策画机才干履行高等说话编写的法度,在接下来的博文中,我们将介绍非托管和托管语音的编译过程。
1.1.2正文
非托管景象的编译过程(C/C++)
纯C/C++的法度凡是运行在一个非托管景象中,类是由头文件(.h)和实现文件(.cpp)构成,每个类形成了一个零丁的编译单位,编译法度时,几个根蒂根基组件会把我们的源代码翻译成二进制代码,接下来我们经由过程以下申明非托管景象的编译过程:
图1 C/C++编译过程
起首是预处理惩罚器,若是在项目中有头文件和宏表达式,那么它将负责包含头文件和翻译所有的宏观表达式。
接下来是编译器,它不是直接生成二进制代码,而是生成汇编代码(.s),这根蒂根基上是所有现代的非布局化说话的共同根蒂根基。
然后,汇编法度把汇编代码翻译成目标代码(.o和.obj文件,机械指令)。
最后链接器,它把所有彼此相干的目标文件和生成的可履行文件或库链接起来。
总而言之,在一般景象下,我们的代码起首翻译成汇编代码,接着翻译成机械指令(二进制代码)。
什么是宏?
在C/C++中,宏是预处理惩罚指令,它有多种应用技巧:包含预定义、创建关键字和前提编译等等。在一般景象下,这些技巧在C++中应用被认为是不好的做法,首要原因是有可能滥用C++供给的语法变更功能,甚至有可能在不知情景象下创建了非标准的说话,宏不遵守一般的源代码编译规矩,因为它经由过程预处理惩罚来处理惩罚,而不是编译器。
托管景象的编译过程(C#/Java)
在托管景象中,编译的过程略有不合,我们熟知的托管说话有C#和Java,接下来,我们将以C#和Java为例介绍在托管景象中的编译过程。
在爱好的IDE中编写代码时,第一个检测我们代码的就是IDE(词法解析),然后,编译成目标文件和链接到动态/静态库或可履行文件进行再次搜检(语法解析),最后一次搜检是运行时搜检。托管景象中的一个共同特点是,编译器不是产生二进制代码,而是中心元代码,称为MSIL - Microsoft Intermediate Language在.NET中或字节码(Bytecode)在Java中。
在那之后,在运行时JIT(Just In Time)编译器将MSIL翻译成二进制代码,这意味着我们的代码在真正应用的时辰才被解析,这容许在CLR(公共说话运行时)预编译和优化我们的代码,实现法度机能的进步,但增长了法度的启动时候,我们也可以应用Ngen(Native Image Generator)预编译我们的法度,从而缩短法度的启动时候,但没有运行时优化的益处。
 
图2 C#的编译过程
.Net Framework就是在Win32 core上添加了一个抽象层,它供给的一个益处就是支撑多说话、JIT优化、主动内存经管和改进安然性;别的一个完全解决规划是WinRT,但这涉及到别的一个主题了,这里不作具体介绍。
图3 Windows API
JIT编译的长处和毛病
JIT编译带来了很多益处,大一个在我看来是机能的上风,它容许CLR(通用说话运行时扮演Assembler组件)只履行须要的代码,例如:假设我们有一个很是大的WPF应用法度,它不是立即加载全部法度,而是CLR开端履行时,我们代码的不合项目组将经由过程一个高效的办法翻译成本地指令,因为它可以或许搜检体系JIT和生成优化的代码,而不是遵守一个预定义的模式。不幸的是,有一个毛病就是启动的过程斗劲慢,这意味着它不实用于加载时候长的包。
JIT的调换规划应用NGen
若是Visual Studio由JIT创建,那么它的启动我们将须要守候几分钟,相反,若是它是应用Ngen(Native Image Generator)编译,它将创建纯二进制可履行文件,若是只推敲速度的题目,那是绝对是正确的选择。
1.1.3总结
在非托管景象中,我们须要知道编译的过程分成编译和连接两个阶段,编译阶段将源法度(.c,.cpp或.h)转换成为目标代码(.o或.obj文件),至于具体过程就是上方说的C/C++编译过程的前三个阶段;链接阶段是把前面转成成的目标代码(obj文件)与我们法度里面调用的库函数对应的代码链接起来形成对应的可履行文件(exe文件)。
托管景象中,编译过程可以分为:词法解析、语法解析、中心代码生成、代码优化和目标代码生成等等过程;无论是.NET还是Java,它们都邑生成中心代码(MSIL或Bytecode),然后把优化后的中心代码翻译成目标代码,最后在法度运行时,JIT将IL翻译成机械码。
无论是托管或非托管说话,它们的编译编译过程是把高等说话翻译成策画机能懂得的机械码,因为编译过程涉及的常识面很广(编译的道理和硬件常识),并且本人的才能有限,也只能简单的描述一下这些过程,若是大师深切懂得编译的道理,我推荐大师看一下《编译道理》。
参考
[1] http://www.developingthefuture.net/compilation-process-and-jit-compiler/
彼此相爱,却不要让爱成了束缚:不如让它成为涌动的大海,两岸乃是你们的灵魂。互斟满杯,却不要同饮一杯。相赠面包,却不要共食一个。一起歌舞欢喜,却依然各自独立,相互交心,却不是让对方收藏。因为唯有生命之手,方能收容你们的心。站在一起却不要过于靠近。—— 纪伯伦《先知》
1.1.1 择要
我们知道策画机不克不及直接懂得高等说话,它只能懂得机械说话,所以我们必必要把高等说话翻译成机械说话,如许策画机才干履行高等说话编写的法度,在接下来的博文中,我们将介绍非托管和托管语音的编译过程。
1.1.2正文
非托管景象的编译过程(C/C++)
纯C/C++的法度凡是运行在一个非托管景象中,类是由头文件(.h)和实现文件(.cpp)构成,每个类形成了一个零丁的编译单位,编译法度时,几个根蒂根基组件会把我们的源代码翻译成二进制代码,接下来我们经由过程以下申明非托管景象的编译过程:
图1 C/C++编译过程
起首是预处理惩罚器,若是在项目中有头文件和宏表达式,那么它将负责包含头文件和翻译所有的宏观表达式。
接下来是编译器,它不是直接生成二进制代码,而是生成汇编代码(.s),这根蒂根基上是所有现代的非布局化说话的共同根蒂根基。
然后,汇编法度把汇编代码翻译成目标代码(.o和.obj文件,机械指令)。
最后链接器,它把所有彼此相干的目标文件和生成的可履行文件或库链接起来。
总而言之,在一般景象下,我们的代码起首翻译成汇编代码,接着翻译成机械指令(二进制代码)。
什么是宏?
在C/C++中,宏是预处理惩罚指令,它有多种应用技巧:包含预定义、创建关键字和前提编译等等。在一般景象下,这些技巧在C++中应用被认为是不好的做法,首要原因是有可能滥用C++供给的语法变更功能,甚至有可能在不知情景象下创建了非标准的说话,宏不遵守一般的源代码编译规矩,因为它经由过程预处理惩罚来处理惩罚,而不是编译器。
托管景象的编译过程(C#/Java)
在托管景象中,编译的过程略有不合,我们熟知的托管说话有C#和Java,接下来,我们将以C#和Java为例介绍在托管景象中的编译过程。
在爱好的IDE中编写代码时,第一个检测我们代码的就是IDE(词法解析),然后,编译成目标文件和链接到动态/静态库或可履行文件进行再次搜检(语法解析),最后一次搜检是运行时搜检。托管景象中的一个共同特点是,编译器不是产生二进制代码,而是中心元代码,称为MSIL - Microsoft Intermediate Language在.NET中或字节码(Bytecode)在Java中。
在那之后,在运行时JIT(Just In Time)编译器将MSIL翻译成二进制代码,这意味着我们的代码在真正应用的时辰才被解析,这容许在CLR(公共说话运行时)预编译和优化我们的代码,实现法度机能的进步,但增长了法度的启动时候,我们也可以应用Ngen(Native Image Generator)预编译我们的法度,从而缩短法度的启动时候,但没有运行时优化的益处。
 
图2 C#的编译过程
.Net Framework就是在Win32 core上添加了一个抽象层,它供给的一个益处就是支撑多说话、JIT优化、主动内存经管和改进安然性;别的一个完全解决规划是WinRT,但这涉及到别的一个主题了,这里不作具体介绍。
图3 Windows API
JIT编译的长处和毛病
JIT编译带来了很多益处,大一个在我看来是机能的上风,它容许CLR(通用说话运行时扮演Assembler组件)只履行须要的代码,例如:假设我们有一个很是大的WPF应用法度,它不是立即加载全部法度,而是CLR开端履行时,我们代码的不合项目组将经由过程一个高效的办法翻译成本地指令,因为它可以或许搜检体系JIT和生成优化的代码,而不是遵守一个预定义的模式。不幸的是,有一个毛病就是启动的过程斗劲慢,这意味着它不实用于加载时候长的包。
JIT的调换规划应用NGen
若是Visual Studio由JIT创建,那么它的启动我们将须要守候几分钟,相反,若是它是应用Ngen(Native Image Generator)编译,它将创建纯二进制可履行文件,若是只推敲速度的题目,那是绝对是正确的选择。
1.1.3总结
在非托管景象中,我们须要知道编译的过程分成编译和连接两个阶段,编译阶段将源法度(.c,.cpp或.h)转换成为目标代码(.o或.obj文件),至于具体过程就是上方说的C/C++编译过程的前三个阶段;链接阶段是把前面转成成的目标代码(obj文件)与我们法度里面调用的库函数对应的代码链接起来形成对应的可履行文件(exe文件)。
托管景象中,编译过程可以分为:词法解析、语法解析、中心代码生成、代码优化和目标代码生成等等过程;无论是.NET还是Java,它们都邑生成中心代码(MSIL或Bytecode),然后把优化后的中心代码翻译成目标代码,最后在法度运行时,JIT将IL翻译成机械码。
无论是托管或非托管说话,它们的编译编译过程是把高等说话翻译成策画机能懂得的机械码,因为编译过程涉及的常识面很广(编译的道理和硬件常识),并且本人的才能有限,也只能简单的描述一下这些过程,若是大师深切懂得编译的道理,我推荐大师看一下《编译道理》。
参考
[1] http://www.developingthefuture.net/compilation-process-and-jit-compiler/
彼此相爱,却不要让爱成了束缚:不如让它成为涌动的大海,两岸乃是你们的灵魂。互斟满杯,却不要同饮一杯。相赠面包,却不要共食一个。一起歌舞欢喜,却依然各自独立,相互交心,却不是让对方收藏。因为唯有生命之手,方能收容你们的心。站在一起却不要过于靠近。—— 纪伯伦《先知》