编译原理里推导的定义
Ⅰ 编译原理笔记9:语法分析树、语法树、二义性的消除
语法分析树和语法树不是一种东西 。习惯上,我们把前者叫做“具体语法树”,其能够体现推导的过程;后者叫做“抽象语法树”,其不体现过程,只关心最后的结果。
语法分析树是语言推导过程的图形化表示方法。这种表示方法反映了语言的实质以及语言的推导过程。
定义:对于 CFG G 的句型,分析树被定义为具有下述性质的一棵树:
推导,有最左推导和最右推导,这两种推导方式在推导过程中的分析树可能不同,但因最终得到的句子是相同的,所以最终的分析树是一样的。
分析树能反映句型的推导过程,也能反映句型的结构。然而实际上,我们往往不关心推导的过程,而只关心推导的结果。因此,我们要对 分析树 进行改造,得到 语法树 。语法树中全是终结符,没有非终结符。而且语法树中没有括号
定义:
说白了,语法树这玩意,就一句话: 叶子全是操作数,内部全是操作符 ,树里没有非终结符也不能有括号。
语法树要表达的东西,是操作符(运算)作用于操作数(运算对象)
举俩例子吧:
【例】: -(id+id) 的语法树:
【例】:-id+id 的语法树:
显然,我们从上面这两个语法树中,直接就能观察出来它们的运算顺序。
【例】:句型 if C then s1 else s2
二义性问题:一个句子可能对应多于一棵语法树。
【例】: 设文法 G: E → E+E | E*E | (E) | -E | id
则,句子 id+id*id、id+id+id 可能的分析树有:
在该例中,虽然 id+id+id 的 “+” 的结合性无论左右都不会影响结果。但万一,万一“+”的含义变成了“减法”,那么左结合和右结合就会引起很大的问题了。
我们在这里讲的“二义性”的“义”并非语义——我们现在在学习的内容是“语法分析器”,尚未到需要研究语言背后含义的阶段。
我们现在讲的“二义性”指的是一个句子对应多种分析树。
二义性的体现,是文法对同一句子有不止一棵分析树。这种问题由【句子产生过程中的某些推导有多于一种选择】引起。悬空 else 问题就可以很好地体现这种【超过一种选择】带来的二义性问题,示例如下。
看下面这么个例子。。
(其实,我感觉这个其实比较像是“说话大喘气”带来的理解歧义问题。。。)上面的产生式中并没体现出来该咋算分一块,所以两种完全不同的句子结构都是合法的。
二义性问题是有救的,大概有以下这三种办法:
这些办法的核心,其实都是将优先级和结合性说明白。
核心:把优先级和结合性说明白
既然要说明白,那就不能让一个非终结符可以直接在当次推导中能推出会带来优先级和结合性歧义的东西。(对分析树的一个内部节点,不会有出现在其下面的分支是相同的非终结符的情况。如果有得选,那就有得歧义了。没得选才能确定地一路走到黑)
改写为非二义文法的二义文法大概有下面这几个特点:
改写的关键步骤:
【例】改写下面的二义文法为非二义文法。图右侧是要达成的优先级和结合性
改写的核心其实就两句话:
所以能够得到非终结符与运算的对应关系(因为不同的运算有不同的优先级,我们想要引入多个优先级就要引入多个新的非终结符。这样每个非终结符就可以负责一个优先级的运算符号,也就是说新的非终结符是与运算有关系的了。因此这里搞出来了“对应关系”四个字)如下:
优先级由低到高分别是 +、 、-,而距离开始符号越近,优先级越低。因此在这里的排序也可以+ -顺序。每个符号对应一层的非终结符。根据所需要的结合性,则可确定是左递归还是右递归,以确定新的产生式长什么样子
【例】:规定优先级和结合性,写出改写的非二义文法
我们已经掌握了一种叫做【改写】的工具,能让我们消除二义性。接下来我们就要用这个工具来尝试搞搞悬空 else 问题!
悬空 else 问题出现的原因是 then 数量多于 else,让 else 有多个可以结合的 then。在二义文法中,由于选哪两个 then、else 配对都可以,故会引起出现二义的情况。在这里,我们规定 else 右结合,即与左边最靠近的 then 结合。
为改写此文法,可以将 S 分为完全匹配(MS)和不完全匹配(UMS)两类。在 MS 中体现 then、else 个数相等即匹配且右结合;在UMS 中 then、else 不匹配,体现 else 右结合。
【例】:用改写后的文法写一个条件语句
经过检查,无法再根据文法写出其他分析树,故已经消除了二义性
虽然二义文法会导致二义性,但是其并非一无是处。其有两个显着的优点:
在 Yacc 中,我们可以直接指定优先级、结合性而无需自己重写文法。
left 表示左结合,right 表示右结合。越往下的算符优先级越高。
嗯就这么简单。。。
我们其实可以把语言本身定义成没有优先级和结合性的。。然后所有的优先、结合都交由括号进行控制,哪个先算就加括号。把一个过程的结束用明确的标志标记出来。
比如在 Ada 中:
在 Pascal 中,给表达式加括号:
Ⅱ 编译原理
C语言编译过程详解
C语言的编译链接过程是要把我们编写的一个C程序(源代码)转换成可以在硬件上运行的程序(可执行代码),需要进行编译和链接。编译就是把文本形式源代码翻译为机器语言形式的目标文件的过程。链接是把目标文件、操作系统的启动代码和用到的库文件进行组织形成最终生成可执行代码的过程。过程图解如下:
从图上可以看到,整个代码的编译过程分为编译和链接两个过程,编译对应图中的大括号括起的部分,其余则为链接过程。
一、编译过程
编译过程又可以分成两个阶段:编译和汇编。
1、编译
编译是读取源程序(字符流),对之进行词法和语法的分析,将高级语言指令转换为功能等效的汇编代码,源文件的编译过程包含两个主要阶段:
第一个阶段是预处理阶段,在正式的编译阶段之前进行。预处理阶段将根据已放置在文件中的预处理指令来修改源文件的内容。如#include指令就是一个预处理指令,它把头文件的内容添加到.cpp文件中。这个在编译之前修改源文件的方式提供了很大的灵活性,以适应不同的计算机和操作系统环境的限制。一个环境需要的代码跟另一个环境所需的代码可能有所不同,因为可用的硬件或操作系统是不同的。在许多情况下,可以把用于不同环境的代码放在同一个文件中,再在预处理阶段修改代码,使之适应当前的环境。
主要是以下几方面的处理:
(1)宏定义指令,如 #define a b。
对于这种伪指令,预编译所要做的是将程序中的所有a用b替换,但作为字符串常量的 a则不被替换。还有 #undef,则将取消对某个宏的定义,使以后该串的出现不再被替换。
(2)条件编译指令,如#ifdef,#ifndef,#else,#elif,#endif等。
这些伪指令的引入使得程序员可以通过定义不同的宏来决定编译程序对哪些代码进行处理。预编译程序将根据有关的文件,将那些不必要的代码过滤掉
(3) 头文件包含指令,如#include "FileName"或者#include <FileName>等。
在头文件中一般用伪指令#define定义了大量的宏(最常见的是字符常量),同时包含有各种外部符号的声明。采用头文件的目的主要是为了使某些定义可以供多个不同的C源程序使用。因为在需要用到这些定义的C源程序中,只需加上一条#include语句即可,而不必再在此文件中将这些定义重复一遍。预编译程序将把头文件中的定义统统都加入到它所产生的输出文件中,以供编译程序对之进行处理。包含到C源程序中的头文件可以是系统提供的,这些头文件一般被放在/usr/include目录下。在程序中#include它们要使用尖括号(<>)。另外开发人员也可以定义自己的头文件,这些文件一般与C源程序放在同一目录下,此时在#include中要用双引号("")。
(4)特殊符号,预编译程序可以识别一些特殊的符号。
例如在源程序中出现的LINE标识将被解释为当前行号(十进制数),FILE则被解释为当前被编译的C源程序的名称。预编译程序对于在源程序中出现的这些串将用合适的值进行替换。
预编译程序所完成的基本上是对源程序的“替代”工作。经过此种替代,生成一个没有宏定义、没有条件编译指令、没有特殊符号的输出文件。这个文件的含义同没有经过预处理的源文件是相同的,但内容有所不同。下一步,此输出文件将作为编译程序的输出而被翻译成为机器指令。
第二个阶段编译、优化阶段。经过预编译得到的输出文件中,只有常量;如数字、字符串、变量的定义,以及C语言的关键字,如main,if,else,for,while,{,}, +,-,*,\等等。
编译程序所要作得工作就是通过词法分析和语法分析,在确认所有的指令都符合语法规则之后,将其翻译成等价的中间代码表示或汇编代码。
优化处理是编译系统中一项比较艰深的技术。它涉及到的问题不仅同编译技术本身有关,而且同机器的硬件环境也有很大的关系。优化一部分是对中间代码的优化。这种优化不依赖于具体的计算机。另一种优化则主要针对目标代码的生成而进行的。
对于前一种优化,主要的工作是删除公共表达式、循环优化(代码外提、强度削弱、变换循环控制条件、已知量的合并等)、复写传播,以及无用赋值的删除,等等。
后一种类型的优化同机器的硬件结构密切相关,最主要的是考虑是如何充分利用机器的各个硬件寄存器存放的有关变量的值,以减少对于内存的访问次数。另外,如何根据机器硬件执行指令的特点(如流水线、RISC、CISC、VLIW等)而对指令进行一些调整使目标代码比较短,执行的效率比较高,也是一个重要的研究课题。
2、汇编
汇编实际上指把汇编语言代码翻译成目标机器指令的过程。对于被翻译系统处理的每一个C语言源程序,都将最终经过这一处理而得到相应的目标文件。目标文件中所存放的也就是与源程序等效的目标的机器语言代码。目标文件由段组成。通常一个目标文件中至少有两个段:
代码段:该段中所包含的主要是程序的指令。该段一般是可读和可执行的,但一般却不可写。
数据段:主要存放程序中要用到的各种全局变量或静态的数据。一般数据段都是可读,可写,可执行的。
UNIX环境下主要有三种类型的目标文件:
(1)可重定位文件
其中包含有适合于其它目标文件链接来创建一个可执行的或者共享的目标文件的代码和数据。
(2)共享的目标文件
这种文件存放了适合于在两种上下文里链接的代码和数据。
第一种是链接程序可把它与其它可重定位文件及共享的目标文件一起处理来创建另一个 目标文件;
第二种是动态链接程序将它与另一个可执行文件及其它的共享目标文件结合到一起,创建一个进程映象。
(3)可执行文件
它包含了一个可以被操作系统创建一个进程来执行之的文件。汇编程序生成的实际上是第一种类型的目标文件。对于后两种还需要其他的一些处理方能得到,这个就是链接程序的工作了。
二、链接过程
由汇编程序生成的目标文件并不能立即就被执行,其中可能还有许多没有解决的问题。
例如,某个源文件中的函数可能引用了另一个源文件中定义的某个符号(如变量或者函数调用等);在程序中可能调用了某个库文件中的函数,等等。所有的这些问题,都需要经链接程序的处理方能得以解决。
链接程序的主要工作就是将有关的目标文件彼此相连接,也即将在一个文件中引用的符号同该符号在另外一个文件中的定义连接起来,使得所有的这些目标文件成为一个能够被操作系统装入执行的统一整体。
根据开发人员指定的同库函数的链接方式的不同,链接处理可分为两种:
(1)静态链接
在这种链接方式下,函数的代码将从其所在地静态链接库中被拷贝到最终的可执行程序中。这样该程序在被执行时这些代码将被装入到该进程的虚拟地址空间中。静态链接库实际上是一个目标文件的集合,其中的每个文件含有库中的一个或者一组相关函数的代码。
(2) 动态链接
在此种方式下,函数的代码被放到称作是动态链接库或共享对象的某个目标文件中。链接程序此时所作的只是在最终的可执行程序中记录下共享对象的名字以及其它少量的登记信息。在此可执行文件被执行时,动态链接库的全部内容将被映射到运行时相应进程的虚地址空间。动态链接程序将根据可执行程序中记录的信息找到相应的函数代码。
对于可执行文件中的函数调用,可分别采用动态链接或静态链接的方法。使用动态链接能够使最终的可执行文件比较短小,并且当共享对象被多个进程使用时能节约一些内存,因为在内存中只需要保存一份此共享对象的代码。但并不是使用动态链接就一定比使用静态链接要优越。在某些情况下动态链接可能带来一些性能上损害。
我们在linux使用的gcc编译器便是把以上的几个过程进行捆绑,使用户只使用一次命令就把编译工作完成,这的确方便了编译工作,但对于初学者了解编译过程就很不利了,下图便是gcc代理的编译过程:
从上图可以看到:
预编译
将.c 文件转化成 .i文件
使用的gcc命令是:gcc –E
对应于预处理命令cpp
编译
将.c/.h文件转换成.s文件
使用的gcc命令是:gcc –S
对应于编译命令 cc –S
汇编
将.s 文件转化成 .o文件
使用的gcc 命令是:gcc –c
对应于汇编命令是 as
链接
将.o文件转化成可执行程序
使用的gcc 命令是: gcc
对应于链接命令是 ld
总结起来编译过程就上面的四个过程:预编译、编译、汇编、链接。了解这四个过程中所做的工作,对我们理解头文件、库等的工作过程是有帮助的,而且清楚的了解编译链接过程还对我们在编程时定位错误,以及编程时尽量调动编译器的检测错误会有很大的帮助的。
Ⅲ 编译原理——S、L属性定义
如果一个语法制导定义的每一个属性都是综合属性,那么就叫做S属性定义。
第二类语法制导定义叫做L属性定义。在产生式中属性之间的依赖图边都是从左到右,不是从右到左。
假设产生式A->X1,X2,...,Xn,而且Xi.a的继承属性与以下几个属性相关:
1.A的继承属性。
2.Xi左边的产生式符号X1,X2,...,X(i-1)的属性。
3.与Xi本身的属性相关,但是只有一种通过Xj属性生成无环依赖图的方式。
S属性定义都是L属性定义。因为S属性只限于综合属性。
Ⅳ 【编译原理】第二章:语言和文法
上述文法 表示,该文法由终结符集合 ,非终结符集合 ,产生式集合 ,以及开始符号 构成。
而产生式 表示,一个表达式(Expression) ,可以由一个标识符(Identifier) 、或者两个表达式由加号 或乘号 连接、或者另一个表达式用括号包裹( )构成。
约定 :在不引起歧义的情况下,可以只写产生式。如以上文法可以简写为:
产生式
可以简写为:
如上例中,
可以简写为:
给定文法 ,如果有 ,那么可以将符号串 重写 为 ,记作 ,这个过程称为 推导 。
如上例中, 可以推导出 或 或 等等。
如果 ,
可以记作 ,则称为 经过n步推导出 ,记作 。
推导的反过程称为 归约 。
如果 ,则称 是 的一个 句型(sentential form )。
由文法 的开始符号 推导出的所有句子构成的集合称为 文法G生成的语言 ,记作 。
即:
例
文法
表示什么呢?
代表小写字母;
代表数字;
表示若干个字母和数字构成的字符串;
说明 是一个字母、或者是字母开头的字符串。
那么这个文法表示的即是,以字母开头的、非空的字符串,即标识符的构成方式。
并、连接、幂、克林闭包、正闭包。
如上例表示为:
中必须包含一个 非终结符 。
产生式一般形式:
即上式中只有当上下文满足 与 时,才能进行从 到 的推导。
上下文有关文法不包含空产生式( )。
产生式的一般形式:
即产生式左边都是非终结符。
右线性文法 :
左线性文法 :
以上都成为正则文法。
即产生式的右侧只能有一个终结符,且所有终结符只能在同一侧。
例:(右线性文法)
以上文法满足右线性文法。
以上文法生成一个以字母开头的字母数字串(标识符)。
以上文法等价于 上下文无关文法 :
正则文法能描述程序设计语言中的多数单词。
正则文法能描述程序设计语言中的多数单词,但不能表示句子构造,所以用到最多的是CFG。
根节点 表示文法开始符号S;
内部节点 表示对产生式 的应用;该节点的标号是产生式左部,子节点从左到右表示了产生式的右部;
叶节点 (又称边缘)既可以是非终结符也可以是终结符。
给定一个句型,其分析树的每一棵子树的边缘称为该句型的一个 短语 。
如果子树高度为2,那么这棵子树的边缘称为该句型的一个 直接短语 。
直接短语一定是某产生式的右部,但反之不一定。
如果一个文法可以为某个句子生成 多棵分析树 ,则称这个文法是 二义性的 。
二义性原因:多个if只有一个else;
消岐规则:每个else只与最近的if匹配。
Ⅳ 编译原理
编译原理):利用编译程序从源语言编写的源程序产生目标程序的过程; 用编译程序产生目标程序的动作。 编译就是把高级语言变成计算机可以识别的2进制语言,计算机只认识1和0,编译程序把人们熟悉的语言换成2进制的。
编译程序把一个源程序翻译成目标程序的工作过程分为五个阶段:词法分析;语法分析;语义检查和中间代码生成
(5)编译原理里推导的定义扩展阅读:
编译程序的语法分析器以单词符号作为输入,分析单词符号串是否形成符合语法规则的语法单位,如表达式、赋值、循环等,最后看是否构成一个符合要求的程序,按该语言使用的语法规则分析检查每条语句是否有正确的逻辑结构,程序是最终的一个语法单位。
编译程序的语法规则可用上下文无关文法来刻画。语法分析的方法分为两种:自上而下分析法和自下而上分析法。自上而下就是从文法的开始符号出发,向下推导,推出句子。
而自下而上分析法采用的是移进归约法,基本思想是:用一个寄存符号的先进后出栈,把输入符号一个一个地移进栈里,当栈顶形成某个产生式的一个候选式时,即把栈顶的这一部分归约成该产生式的左邻符号。
Ⅵ 编译原理-文法定义
文法定义公式如下:
Chomsky 文法分类将文法分为四种,0型文法( PSG )、1型文法( CSG )、2型文法( CFG )和3型文法( RG )。
又被称为无限制文法(Unrestricted Grammar), 或者短语结构文法(Phrase Structure Grammar)
定义: 对于产生式 α→β , α 至少包含一个非终结符。
为什么要叫无限制文法,明明它要求产生式的左部必须包含一个非终结符。
又被称为上下文有关文法(Context-Sensitive Grammar)
定义:对于产生式 α→β , |α| <= |β| , 仅仅 S→ε 除外
为什么叫做上下文有关文法?
一般情况下,这种产生式的形式为 α1Aα2→α1βα2
又被称为上下文无关文法(Context-Free Grammar)
定义:对任一产生式 α→β ,都有 α∈VN,β∈(VN∪VT)*
为什么叫上下文无关文法?
又被称为正则文法(Regular Grammar,RG),分为右线性(Right Linear)文法和左线性(Left Linear)文法。
定义: 对任一产生式 α→β ,都有 α∈VN,β最多两个字符元素,如果有二个字符必须是(终结符+非终结符)的格式,如果是一个字符,那么必须是终结符。
根据产生式右部非终结符位置不同,分为右线性文法和左线性文法。
可以看出,不同文法就是对产生式进行逐层的限制,所以各个文法是包含关系,即0型文法包含1型文法;1型文法又包含2型文法;2型文法最后包含3型文法。
Ⅶ 什么是(文法的)规范推导(编译原理))
规范推导:最右推导
最右推导、最左推导、规范推导、规范句型
对于文法:G[S]:S → aAS | a
A → SbA | SS | ba
最右推导:S=> aA S =>a A a=>aSb A a
=>a S bbaa=>aabbaa(每次只推导 最右边 的非终结符,直到推导完毕)
(得到的句型为 规范句型 )
最左推导: S=>a A S=>a S bAS=>aab A S
=>aabba S =>aabbaa(与最右推导类比理解)
Ⅷ 编译原理全部的名词解释
书上有别那么懒!.
编译过程的六个阶段:词法分析,语法分析,语义分析,中间代码生成,代码优化,目标代码生成
解释程序:把某种语言的源程序转换成等价的另一种语言程序——目标语言程序,然后再执行目标程序.解释方式是接受某高级语言的一个语句输入,进行解释并控制计算机执行,马上得到这句的执行结果,然后再接受下一句.
编译程序:就是指这样一种程序,通过它能够将用高级语言编写的源程序转换成与之在逻辑上等价的低级语言形式的目标程序(机器语言程序或汇编语言程序).
解释程序和编译程序的根本区别:是否生成目标代码
句子的二义性(这里的二义性是指语法结构上的.):文法G[S]的一个句子如果能找到两种不同的最左推导(或最右推导),或者存在两棵不同的语法树,则称这个句子是二义性的.
文法的二义性:一个文法如果包含二义性的句子,则这个文法是二义文法,否则是无二义文法.
LL(1)的含义:(LL(1)文法是无二义的; LL(1)文法不含左递归)
第1个L:从左到右扫描输入串 第2个L:生成的是最左推导
1 :向右看1个输入符号便可决定选择哪个产生式
某些非LL(1)文法到LL(1)文法的等价变换: 1. 提取公因子 2. 消除左递归
文法符号的属性:单词的含义,即与文法符号相关的一些信息.如,类型、值、存储地址等.
一个属性文法(attribute grammar)是一个三元组A=(G, V, F)
G:上下文无关文法.
V:属性的有穷集.每个属性与文法的一个终结符或非终结符相连.属性与变量一样,可以进行计算和传递.
F:关于属性的断言或谓词(一组属性的计算规则)的有穷集.断言或语义规则与一个产生式相联,只引用该产生式左端或右端的终结符或非终结符相联的属性.
综合属性:若产生式左部的单非终结符A的属性值由右部各非终结符的属性值决定,则A的属性称为综合属
继承属性:若产生式右部符号B的属性值是根据左部非终结符的属性值或者右部其它符号的属性值决定的,则B的属性为继承属性.
(1)非终结符既可有综合属性也可有继承属性,但文法开始符号没有继承属性.
(2) 终结符只有综合属性,没有继承属性,它们由词法程序提供.
在计算时: 综合属性沿属性语法树向上传递;继承属性沿属性语法树向下传递.
语法制导翻译:是指在语法分析过程中,完成附加在所使用的产生式上的语义规则描述的动作.
语法制导翻译实现:对单词符号串进行语法分析,构造语法分析树,然后根据需要构造属性依赖图,遍历语法树并在语法树的各结点处按语义规则进行计算.
中间代码(中间语言)
1、是复杂性介于源程序语言和机器语言的一种表示形式.
2、一般,快速编译程序直接生成目标代码.
3、为了使编译程序结构在逻辑上更为简单明确,常采用中间代码,这样可以将与机器相关的某些实现细节置于代码生成阶段仔细处理,并且可以在中间代码一级进行优化工作,使得代码优化比较容易实现.
何谓中间代码:源程序的一种内部表示,不依赖目标机的结构,易于代码的机械生成.
为何要转换成中间代码:(1)逻辑结构清楚;利于不同目标机上实现同一种语言.
(2)便于移植,便于修改,便于进行与机器无关的优化.
中间代码的几种形式:逆波兰记号 ,三元式和树形表示 ,四元式
符号表的一般形式:一张符号表的的组成包括两项,即名字栏和信息栏.
信息栏包含许多子栏和标志位,用来记录相应名字和种种不同属性,名字栏也称主栏.主栏的内容称为关键字(key word).
符号表的功能:(1)收集符号属性 (2) 上下文语义的合法性检查的依据: 检查标识符属性在上下文中的一致性和合法性.(3)作为目标代码生成阶段地址分配的依据
符号的主要属性及作用:
1. 符号名 2. 符号的类型 (整型、实型、字符串型等))3. 符号的存储类别(公共、私有)
4. 符号的作用域及可视性 (全局、局部) 5. 符号变量的存储分配信息 (静态存储区、动态存储区)
存储分配方案策略:静态存储分配;动态存储分配:栈式、 堆式.
静态存储分配
1、基本策略
在编译时就安排好目标程序运行时的全部数据空间,并能确定每个数据项的单元地址.
2、适用的分配对象:子程序的目标代码段;全局数据目标(全局变量)
3、静态存储分配的要求:不允许递归调用,不含有可变数组.
FORTRAN程序是段结构,不允许递归,数据名大小、性质固定. 是典型的静态分配
动态存储分配
1、如果一个程序设计语言允许递归过程、可变数组或允许用户自由申请和释放空间,那么,就需要采用动态存储管理技术.
2、两种动态存储分配方式:栈式,堆式
栈式动态存储分配
分配策略:将整个程序的数据空间设计为一个栈.
【例】在具有递归结构的语言程序中,每当调用一个过程时,它所需的数据空间就分配在栈顶,每当过程工作结束时就释放这部分空间.
过程所需的数据空间包括两部分
一部分是生存期在本过程这次活动中的数据对象.如局部变量、参数单元、临时变量等;
另一部分则是用以管理过程活动的记录信息(连接数据).
活动记录(AR)
一个过程的一次执行所需要的信息使用一个连续的存储区来管理,这个区 (块)叫做一个活动记录.
构成
1、临时工作单元;2、局部变量;3、机器状态信息;4、存取链;
5、控制链;6、实参;7、返回地址
什么是代码优化
所谓优化,就是对代码进行等价变换,使得变换后的代码运行结果与变换前代码运行结果相同,而运行速度加快或占用存储空间减少.
优化原则:等价原则:经过优化后不应改变程序运行的结果.
有效原则:使优化后所产生的目标代码运行时间较短,占用的存储空间较小.
合算原则:以尽可能低的代价取得较好的优化效果.
常见的优化技术
(1) 删除多余运算(删除公共子表达式) (2) 代码外提 +删除归纳变量+ (3)强度削弱; (4)变换循环控制条件 (5)合并已知量与复写传播 (6)删除无用赋值
基本块定义
程序中只有一个入口和一个出口的一段顺序执行的语句序列,称为程序的一个基本块.
给我分数啊.