C/C++, Java和C#的编译过程解析
原文地址:http://www.cnblogs.com/rush/p/3155665.html
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(词法分析),然后,编译成目标文件和链接到动态/静态库或可执行文件进行再次检查(语法分析),最后一次检查是运行时检查。托管环境的共同特点是:编译器不直接编译成机器码,而是中间代码,在.NET中称为MSIL - Microsoft Intermediate Language,Java是字节码(Bytecode)
在那之后,在运行时JIT(Just In Time)编译器将MSIL翻译成机器码,这意味着我们的代码在真正使用的时候才被解析,这允许在CLR(公共语言运行时)预编译和优化我们的代码,实现程序性能的提高,但增加了程序的启动时间,我们也可以使用Ngen(Native Image Generator)预编译我们的程序,从而缩短程序的启动时间,但没有运行时优化的优点。(JeffWong的补充Java是先通过编译器编译成Bytecode,然后在运行时通过解释器将Bytecode解释成机器码;C#是先通过编译器将C#代码编译成IL,然后通过CLR将IL编译成机器代码。所以严格来说Java是一种先编译后解释的语言,而C#是一门纯编译语言,且需要编译两次。)

图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翻译成机器码。
无论是托管或非托管语言,它们的编译编译过程是把高级语言翻译成计算机能理解的机器码,由于编译过程涉及的知识面很广(编译的原理和硬件知识),而且本人的能力有限,也只能简单的描述一下这些过程,如果大家希望深入了解编译的原理,我推荐大家看一下《编译原理》。
C/C++, Java和C#的编译过程解析的更多相关文章
- [译]C++, Java和C#的编译过程解析
1.1.1 摘要 我们知道计算机不能直接理解高级语言,它只能理解机器语言,所以我们必须要把高级语言翻译成机器语言,这样计算机才能执行高级语言编写的程序,在接下来的博文中,我们将介绍非托管和托管语音的编 ...
- U-Boot编译过程解析
解压u-boot-2010.03.tar.bz2就可以得到全部U-Boot源程序.在顶层目录下有29个子目录,分别存放和管理不同的源程序.这些目录中所要存放的文件有其规则,可以分为3类. ● 与处理器 ...
- Java编译过程、c/c++编译过程区别
Java编译原理 1.Java编译过程与c/c++编译过程不同 Java编译程序将java源程序编译成jvm可执行代码--java字节码. c/c++编译过程: 当C编译器编译生成一个对象的代码时,该 ...
- java编译过程(字节码编译和即时编译)
Javac编译与JIT编译 简介: 编译包括两种情况: 1,源码编译成字节码 2,字节码编译成本地机器码(符合本地系统专属的指令) 解释执行也包括两种情况: 1,源码解释执行 2,字节码解释执行 解释 ...
- Java源代码编译过程
编译其本质是将一种语言规范转换成另一种语言规范,即将Java语言规范转换为JVM虚拟机语言规范.结果就是.java文件到.class文件. 对于C/C++编译直接将高级语言转换为机器语言,Java ...
- C++, Java和C#的编译、链接过程解析
总是感觉java是解释性语言,转载下一篇感觉写的容易理解的文章 转自 http://www.cnblogs.com/rush/p/3155665.html 1.1.1 摘要 我们知道计算机不能直接理解 ...
- java代码编译过程
简单随笔 java程序需要先编译成class文件然后才能执行,由于是编程成立机器代码,虚拟机加载内存的时候更快的执行. java文件编译成class文件步骤如下: 1)词法分析,检查每一个关键字单词是 ...
- Android工程的编译过程
现在很多人想对Android工程的编译和打包进行自动化,比如建立每日构建系统.自动生成发布文件等等.这些都需要我们对Android工程的编译和打包有一个深入的理解,至少要知道它的每一步都做了什么,需要 ...
- Linux系统GCC常用命令和GCC编译过程描述
前言: GCC 原名为 GNU C 语言编译器(GNU C Compiler),因为它原本只能处理 C语言.GCC 很快地扩展,变得可处理 C++.后来又 扩展能够支持更多编程语言,如Fortran. ...
随机推荐
- SqlSever基础 union 将得到的横表变为纵表
镇场诗:---大梦谁觉,水月中建博客.百千磨难,才知世事无常.---今持佛语,技术无量愿学.愿尽所学,铸一良心博客.------------------------------------------ ...
- Java反序列化漏洞通用利用分析
原文:http://blog.chaitin.com/2015-11-11_java_unserialize_rce/ 博主也是JAVA的,也研究安全,所以认为这个漏洞非常严重.长亭科技分析的非常细致 ...
- JS学习笔记(三) 对象
参考资料: 1. http://www.w3school.com.cn/js/js_objects.asp ☂ 知识点: ☞ Javascript中的所有事物都是对象. ☞ Javascript是基于 ...
- 利用JDK的中Proxy动态代理实现Spring的AOP技术
首先给出设计模式静态代理与动态代理的学习: http://layznet.iteye.com/blog/1182924 讲的不错 然后我们实现AOP 就要求我们对委托的所有方法的调用实现拦截 代理 ...
- 2013 Multi-University Training Contest 3
HDU-4622 Reincarnation 题意:给定一个字符串,有Q次询问,每次询问得出区间[L, R]内有多少个不同的子串. 分析:后缀数组搞,不过hash+dp也能够搞定这题,详解见http: ...
- iOS - UITabBarController
前言 NS_CLASS_AVAILABLE_IOS(2_0) @interface UITabBarController : UIViewController <UITabBarDelegate ...
- tomcat 启用Gzip 压缩进行优化
打开conf/server.xml文件可以看到: <!-- Define a non-SSL HTTP/1.1 Connector on port 8080 --> <Con ...
- winform打开唯一窗体、构造函数传值
制作登入窗体: 制作一个登陆窗体,实现点击按钮关闭此窗体并打开另一个窗体 直接在按钮点击事件中,实例化一个想要打开的窗体 使用show方法打开,并把登陆窗体的visible属性改为false Form ...
- [转载] DevOps年中盘点:国外最受欢迎的10篇技术文章
本文根据高效运维系列微信群的群友投稿整理而成.“高效运维”公众号作为本系列群的官方唯一公众号,原创并独家首发. 欢迎关注“高效运维”公众号,以免费参加「运维讲坛」每月一次的线下交流活动:并抢先赏阅干货 ...
- [转载] iptables配置实践
原文: http://wsgzao.github.io/post/iptables/ iptables配置实践 By wsgzao 发表于 2015-07-24 文章目录 1. 前言 2. 更新历史 ...