编译系统和运行时的系统

编译系统和运行时的系统(参照编译原理第三版第11章)

源程序———预处理器———修改后的源程序——编译器———汇编程序————汇编器————可重定位的目标程序————链接器(加入库文件和可重定位的目标文件)————可执行的目标程序

大多数编译系统提供一个驱动程序来调用预处理器、编译器、汇编器、链接器、以支持用户完成从源程序到可执行的目标文件。比如GCC。

如 gcc -v-o swap main.c swap.c

预处理器:

预处理器产生编译器的输入,主要有以下功能:

1.文件包含:

预处理器可以把源程序文件中的包含声明(#include)展开为程序正文,#include<stdio.h>,系统会在标准路径下搜素stdio.h,再用stdio.h中的内容代替这个语句。

2.宏展开

C程序可以用#define来定义宏,一个宏定义给出一段C代码的缩写,预处理器将源程序文件中出现的宏的引用展开相应的宏定义,称为宏展开。

3.条件编译

预处理器根据#if和#ifdef等编译命令及其后的条件,将源程序中的某部分包含进来或排除在外,通常把排除在外的语句换成空行。

编译器:

将C程序文件翻译成

汇编器:

汇编语言翻译为机器语言的程序。一般而言,汇编生成的是目标代码,需要经链接器(Linker)生成可执行代码才可以执行。

最简单的汇编器对输入要进行两次扫描,第一遍,汇编器扫描输入,将表示存储单元的所有标识符都存入符号表,并分配地址。

第二遍,汇编器再次扫描输入,将每个操作码都翻译机器语言对应的位串,并将代表存储单元的每个标识符翻译成符号表中的为这个标识符分配的地址。

链接器:

1.可重定位的目标文件 它包含二进制代码和数据,可以和其他可重定位目标文件组装或一个可执行的目标文件。

2.可执行的目标文件

它包含二进制代码和数据,可以直接被复制到内存并被执行。

(一)静态链接库与动态链接库都是共享代码的方式,如果采用静态链接库,lib中的指令都全部被直接包含在最终生成的exe文件中了。但是若使用dll动态链接库,该dll不必被包含在最终的exe文件中,执行文件执行时可以动态地引用和卸载这个与exe独立的dll文件(二)静态链接库不能再包含其他的动态链接库或者静态库,而在动态链接库中还可以再包含其他的动态或静态链接库。 使用差别静态链接库动态链接库使用的区别在于它允许可执行模块(dll或exe文件)仅包含在运行时定位dll函数的可执行代码的所需信息。静态链接库的使用中,连接器从静态链接库获取所有被引用的函数,并将库同代码一起放到可执行文件中。

原文地址:https://www.cnblogs.com/hcr1995/p/9643221.html

时间: 2024-08-29 18:52:56

编译系统和运行时的系统的相关文章

探讨:编译时常量和运行时常量

编译时常量和运行时常量 C#有2种不同的常量定义方式:编译时常量(compile-time)和运行时常量(runtime).他们的行为方式有很大的不同,如果选用了错误的一个,那么将让程序的性能和正确性产生商榷.当然,一个系统最好没有任何问题,但是如果一定会存在一个问题,那么一个稍慢的但强壮的系统比一个速度更快的但很脆弱的系统要好.基于以上理由,在二者选其一的时候,你最好选择运行时常量. 运行时常量以 readonly 关键字定义,编译时是常量以 const 关键字定义: public const

Java虚拟机系列一:一文搞懂 JVM 架构和运行时数据区

前言 之前写博客一直比较随性,主题也很随意,就是想到什么写什么,对什么感兴趣就写什么.虽然写起来无拘无束,自在随意,但也带来了一些问题,每次写完一篇后就要去纠结下一篇到底写什么,看来选择太多也不是好事儿,更重要的是不成体系的内容对读者也不够友好.所以以后的博客尽量按系列来写,不过偶尔也会穿插其他的内容.接下来一段时间我会把写博客的重点放在 JVM (Java Virtual Machine) 和 JUC (java util concurrent ) 上,对 Java 虚拟机和 Java 并发编

一文搞懂 JVM 架构和运行时数据区 (内存区域)

前言 了解 JVM 是对 Java 开发人员的基本要求,JVM 的相关内容自然也成了现在 Java 程序员面试的重要考点.不过估计很多小伙伴和我一样,长时间醉心于 CRUD,却忘了去了解一下更底层.更基础的东西,殊不知这些才是决定你能在这条路上走多远的关键因素,那接下来我们就一起来深入学习一下看似神秘的 JVM 吧.JVM 总体来看内容还是很多的,我会把最重要的内容介绍给大家,不过如果你有时间和精力的话,还是推荐你去看一下<深入理解Java虚拟机>这本书,确实是有口皆碑.本文也会引用很多此书的

c++对MFC消息映射机制和运行时类型识别的理解

对MFC消息映射机制和运行时类型识别的理解 对MFC消息映射机制的理解 MFC中派生于Cobject的每个类都有一个消息映射表,所有MFC窗口都有一个同样的窗口过程AfxWndProc(),AfxWndProc的参数列表中有一个是窗口句柄,在AfxWndProc函数中将句柄(HWND)转换成了窗口指针(CWnd*),通过这个窗口指针就可以获得该窗口的消息映射表.对于WM_COMMAND这类特殊消息,将依据C++的虚函数多态机制来决定调用哪个类的函数. 对MFC运行时类型识别的理解 定义一个CRu

关于指针变量编译和运行时

指针变量编译时只能运行编译时的方法,不能调用运行时类型的方法,即使它实际所指对象确实包含该方法. Father* fa=[[Son alloc]init]; 编译时是:Father 运行时时:Son 解决方法: 强制转换成子类类型,这样 编译和运行时的类型就相同了 //下面编译时类型和运行时类型不一样,多态发生 FKBase* ploymophicBc=[[FKSubclass alloc]init]; [ploymophicBc base]; [ploymophicBc test]; //FK

编译和运行时的界限在哪儿?

两个概念: 一,编译单元:一个.java文件就是一个编译单元.一个.java文件会被编译成一个或多个.class文件.在eclipse等IDE中,默认自动编译,即,一旦.java文件被改动则重新编译并产生.class文件. 二,类的加载:一旦已运行的程序第一次访问一个类的静态数据或者创建一个类的对象时,jvm就会根据包名及类名到classpath下的对应文件夹中找到相应的.class文件将其加载到内存中,此时,程序进入运行时. 所以,编译期和运行时的物理边界是类的加载时. 如果一段程序在运行时每

方法区和运行时常量区溢出 转

方法区和运行时常量池溢出 由于运行时常量池是方法区的一部分,因此这两个区域的溢出测试就放在一起进行.前面提到JDK 1.7开始逐步“去永久代”的事情,在此就以测试代码观察一下这件事对程序的实际影响. String.intern()是一个Native方法,它的作用是:如果字符串常量池中已经包含一个等于此String对象的字符串,则返回代表池中这个字符串的String对象:否则,将此String对象包含的字符串添加到常量池中,并且返回此String对象的引用.在JDK 1.6及之前的版本中,由于常量

vue.js2.0的独立构建和运行时构建

转自:https://jingsam.github.io/2016/10/23/standalone-vs-runtime-only-build-in-vuejs2.html?utm_source=tuicool&utm_medium=referral 在使用 Vue.js 2.0 时,有独立构建(standalone)和运行时构建(runtime-only)两种版本可供选择.而在 Vue.js 1.0 中,却没有这种版本区别.到底该使用哪一个版本?这让我有点懵逼的感觉.本着知其然还要知其所以然

什么叫编译时和运行时

以前经常听说编译时和运行时的概念.但没太搞明白具体代表啥意思.后面花了点时间研究了下.总算知道个大概意思了. 编译时 编译时顾名思义就是正在编译的时候.那啥叫编译呢?就是编译器帮你把源代码翻译成机器能识别的代码.(当然只是一般意义上这么说,实际上可能只是翻译成某个中间状态的语言.比如Java只有JVM识别的字节码,C#中只有CLR能识别的MSIL.另外还有啥链接器.汇编器.为了了便于理解我们可以统称为编译器) 那编译时就是简单的作一些翻译工作,比如检查老兄你有没有粗心写错啥关键字了啊.有啥词法分