1、第8章 语法制导翻译和中间代码生成,数计学院 宋彩芳,培训笔记,义务教育使我们睁开眼,高等教育使我们站起来; 精神自由和教学秩序 有考试无文法,靠记忆力被动接受知识永远不是自己的;不会学习也是文盲; 教育是影响,是引发,是心灵之约;,主要内容,属性文法 语法制导翻译概论 计算语义规则 S-属性文法和自下而上翻译 L-属性文法和自上而下翻译 中间代码的形式 简单赋值语句的翻译 布尔表达式的翻译 控制结构的翻译 说明语句的翻译 数组和结构的翻译,主要内容,中间代码的形式 简单赋值语句的翻译 布尔表达式的翻译 控制结构的翻译 说明语句的翻译 数组和结构的翻译,中间代码的形式,编译器各阶段的完整输出,
2、均可以被认为是源程序的某种中间表示。 编译器前端 词法分析记号流 语法分析语法树 语义分析中间代码 本章讨论的是中间代码生成器输出的中间表示,称之为中间代码。 中间代码实际上应起一个编译器前端与后端分水岭的作用。 生成中间代码的好处: 再目标比较容易 独立于机器的优化可用于这种中间代码,中间代码的形式,介绍几种常用的中间表示: 逆波兰记号(后缀表示) 三元式和树形表示 四元式,中间代码的形式,逆波兰记号( 后缀表示) 表达式E的后缀表示可以如下归纳定义 如果E是变量或常数,那么E的后缀表示就是E本身。 如果E是形式为E1 opE2的表达式,那么E的后缀表示是E1 E2 op,其中E1和E2分别
3、是E1和E2的后缀表示。 如果E是形式为(E1)的表达式,那么E1的后缀表示也是E的后缀表示。,中间代码的形式,后缀表示不需要括号 (8 4) + 2 的后缀表示是8 4 2 + 后缀表示很容易拓广到含一元算符的表达式 后缀表示也可以拓广到表示赋值语句和控制语句,但很难用栈来描述它的计算,中间代码的形式,后缀式的特点: 操作符在前,操作数紧随其后,无需用括号限制运算的优先级和结合性。 后缀表示的最大优点是便于计算机处理表达式 利用一个栈,自左向右地扫描表达式的后缀表示,遇到运算对象,进栈;遇到运算符,出栈相应个数的运算对象计算,并将结果进栈。,中间代码的形式,计算后缀式的虚拟机 输入 后缀式
4、输出 计算结果 方法 采用下述过程进行计算,最终结果留在栈中。x = first_token;while(!end_of_exp )if (x in operators)push x; - 操作数进栈else pop(operators); - 算符,弹出操作数push(evaluate); - 计算,并将结果进栈next(x);,中间代码的形式,后缀式计算 算术表达式3+5+8的后缀式为35+8+。(# 35+8+# 进栈)(#3 5+8+# 进栈)(#35 +8+# 弹出3和5,计算3+5,结果进栈)(#8 8+# 进栈)(#88 +# 弹出8和8,计算8+8,结果进栈)(#16 # ),
5、中间代码的形式,将后缀式推广到其他语句 后缀式并不局限于二元运算的表达式,可以推广到任何语句,只要遵守操作数在前,操作符紧跟其后的原则即可。 语句:if e then x else y 它的后缀式可以写为:e x y if-then-else (1)上述表示中,e、x和y均需计算。而实际上,根据条件e的取值,x和y不能都计算:e p1 jez x p2 jump p1: y p2: (2)其中: p1和p2分别是标号; p1 jez表示e的结果为0(假)则转向p1; p2 jump表示无条件转向p2。 与 (1)比较,(2)中的if-then-else被分解,首先计算e,根据e的结果是否为真,
6、决定计算x还是计算y。,三元式和树形表示,三元式主要由三部分组成:,(OP,arg1, arg2),其中OP是运算符,,arg1,arg2分别是第一和第二两个运算对象。,当OP是一目运算时,常常将运算对象定义为arg1。,中间代码的形式,例如 a+b*c 的 三元式序列:,(1) ( * , b , c ),(2) ( + , a , (1) ),运算对象是指向符号表的某一项或指向三元式表的某一项。,中间代码的形式,1. 三元式出现的顺序和语法成份的 计值顺序相一致。,三元式的特点:,2. 三元式之间的联系是通过指示器实现的。,中间代码的形式,树形表示,A * B + C*D,+,C,*,A,
7、*,B,D,末端结点表示一个运算对象, 每一个内结点表示一个一元或二元运算符。,树形表示是三元式的翻版,(3)+,(1)*,(2)*,C,A,B,D,中间代码的形式,四元式主要由四部分组成:,(OP,arg1, arg2, result),其中OP是运算符,,arg1,arg2分别是第一和第二两个运算对象。,当OP是一目运算时,常常将运算对象定义为arg1。,中间代码的形式,四元式的第四个分量result是编译程序为存放中间运算结果而临时引进的变量,常称为临时变量,如Ti,也可以是用户自定义变量,如X。,例如 X a*bc/d 的 四元式序列:,(1) ( *, a, b, T1 ),(2)
8、( /, c, d, T2 ),(3) ( +, T1, T2, T3 ),(4) ( =, T3, -, X ),中间代码的形式,2. 四元式之间的联系是通过临时变量实 现的,这样易于调整和变动四元式。,1. 四元式出现的顺序和语法成份的计值 顺序相一致。,四元式的特点:,3. 便于优化处理。,中间代码的形式,编译系统中,有时将四元式表示成另一种更直观,更易理解的形式三地址代码或三地址语句。,result : arg1 OP arg2,三地址语句:语句中是三个量的赋值语句, 每个量占一个地址。,三地址代码形式定义为:,中间代码的形式,例如 X a*bc/d 的 四元式序列:,(1) ( *,
9、 a, b, T1 ),(2) ( /, c, d, T2 ),(3) ( +, T1, T2, T3 ),(4) ( =, T3, -, X ),相应的三地址语句序列为:,(1)T1a*b,(2)T2c/d,(3)T3T1T2,(4)XT3,中间代码的形式,例1. a + b * ( c + d )的逆波兰式,a bc d + * +,中间代码的形式,t1= a,t2= c,t3= t2 + d,t5= t1+ t4,a + b * ( c + d )的四元式表示,t4= b* t3,中间代码的形式,i( i /( i i ) )的逆波兰式,i( i /( i i ) )的四元式,t1= i
10、 i,t2= i / t1,t3= i t2,i i i i /,例2.,中间代码的形式,中间代码的形式,介绍几种常用的中间表示: 逆波兰记号(后缀表示) 三元式和树形表示 四元式,中间代码的形式,(jump,-,-,L)可简写为goto L (jrop,B,C,L)可简写为if B rop C goto L (case, V,L,-),各种语句的翻译,思考问题: 描述文法,适当地改写文法; 生成的中间代码形式 翻译规则,含一定的语法规则;,主要内容,中间代码的形式 简单赋值语句的翻译 布尔表达式的翻译 控制结构的翻译 说明语句的翻译 数组和结构的翻译,预备知识:符号表的中名字,在三地址代码中
11、直接用名字表示运算对象 实际应该把名字理解为它们在符号表中的名字 编译器在处理表达式、赋值语句等构造中的名字时,需在符号表中查找它的定义,获得它的属性,然后生成四元式中使用它在符号表中的位置指针。,符号表的中名字,id的属性 name:组成该名字的字符序列 lookup(id.name):根据名字查找符号表中是否存在该名字的条目,有则返回指针,否则返回nil E的属性 place:符号表条目的地址 newTemp:产生一个新的临时变量的名字,并返回一整数码; emit函数:输出四元式到输出文件;,简单赋值语句的翻译,赋值语句文法: Eid := E EE+E|E*E|-E|(E)|id 翻译内
12、容: 中间代码生成(四元式): 其他语法检查: 如先定义后使用: 类型检查: 检查标识符的种类(kind),判断是否为变量名;,emit(t := arg1 op arg2);,E1.type=int AND E2.type=int,p = lookup(id.name) ;,产生式和语义描述:,(,1,) S,id := E,P,:=lookup,(,id.name),;,if P,nil then emit( P,“,:=,”,E.place),else error ,简单赋值语句的翻译,(2) EE1+E2 E.place:= newtemp;emit(E.place“:=” E1.pl
13、ace“+”E2.place) (3) EE1*E2 E.place:= newtemp;emit(E.place“:=” E1.place“*”E2.place),(4) E - E1 E.place:=newtemp;emit(E.place“:=”“uminus” E1.place) (5) E( E1) E.place:= E1.place (6) Eid E.place:=newtemp; P:=lookup(id.name);if Pnil then E.place:=Pelse error,简单赋值语句的翻译,简单赋值语句的翻译,增加类型检查的赋值语句的翻译 EE1*E2 E.p
14、lace:= newtemp; if E1.type=int AND E2.type=int then begin emit(E.place“:=” E1.place“*”E2.place)E.type := int end else begin t:= newtempemit(t, “:=” ,“itr”,E2.place)emit(E.place“:=” E1.place“*”t)E.type := realend,主要内容,中间代码的形式 简单赋值语句的翻译 布尔表达式的翻译 控制结构的翻译 说明语句的翻译 数组和结构的翻译,布尔表达式,布尔表达式有两个基本目的 计算逻辑值 如:x=a
15、or b 在控制流语句中用作条件表达式 如if C then .,while C do .等 本节所用的布尔表达式文法 E E or E | E and E | not E | ( E )| id rop id | true | false 布尔运算的优先级与结合性(从高到低): not and or 例如: a*by or not z 等价于: (a*b)y) or (not z),布尔表达式,布尔表达式的完全计算(数值表示的直接计算)(举例) 值的表示数值化,其计算类似于算术表达式的计算 1表示true, 0表示false。 or、and、not与+、*、-(一元)对应: 布尔表达式的优化
16、计算 只计算部分表达式; 含布尔函数调用的表达式,上两种方法未必等价,由程序设计语言的语义而定;,布尔表达式,例:对布尔表达式a or b and not c采用完全计算: (t=a+b*(-c)) t1 = not c t2 = b and T1 t3 = a or t2 对于关系运算的表达式ab的计算 可看成等价的条件语句:if ab then 1 else 0 翻译成如下固定的三地址码序列 (1) if ab goto (4) (2) t = 0 (3) goto (5) (4) t = 1 (5) .,布尔表达式,布尔表达式ab or cd and ef的直接计算 序号 产生式 四元式
17、 (1) E1ab (1) if ab goto (4)(2) t1 = 0(3) goto (5)(4) t1 = 1 (2) E2cd (5) if cd goto (8)(6) t2 = 0(7) goto (9)(8) t2 = 1 (3) E3ef (9) if ef goto (12)(10) t3 = 0(11) goto (13)(12) t3 = 1 (4) E4E2 and E3 (13) t4 = t2 and t3 (5) E5E1 or E4 (14) t5 = t1 or t4,布尔表达式,数值表示与直接计算的语法制导翻译 全程量nextstat:给出下一四元式序号
18、,调用一次emit,nextstat加1。 语义规则: (1)EE1 or E2 E.place = newtemp; emit(E.place = E1.place or E2.place); (2) |E1 and E2 E.place = newtemp; emit(E.place = E1.place and E2.place); (3) |not E1 E.place = newtemp; emit(E.place = not E1.place); (4) |(E1) E.place = E1.place;,布尔表达式,(5) |id1 rop id2 E.place = newte
19、mp;emit(if id1.place rop id2.place goto nextstat+3);emit(E.place = 0);emit(goto nextstat+2);emit(E.place = 1); (6) |true E.place = newtemp; emit(E.place = 1); (7) |false E.place = newtemp; emit(E.place = 0);,(1) if ab goto (4) (2) t1 = 0 (3) goto (5) (4) t1 = 1 (5) .,布尔表达式,布尔表达式的“短路”计算 (以if-then-els
20、e的方式解释布尔表达式): B1 or B2 定义成 if B1 then true else B2 B1 and B2 定义成 if B1 then B2 else false not B1 定义成 if B1 then false else true 对布尔表达式a or b and not c采用短路计算,则等价于下述解释:if a then trueelse if bthen if c then false else trueelse false,t1:= not c t2:= b and t1 t3:= a or t2,控制语句中布尔表达式的翻译,出现在if-then;if-then
21、-else和while-do等语句中的布尔表达式E的翻译; 这三种语句的语法为: S if E then S1| if E then S1 else S2 | while E do S1,控制语句中布尔表达式的翻译,例:再考虑布尔表达式ab or cd and ef的翻译:,(1)if ab goto E.true (2)goto 3 (3)if cd goto 5 (4)goto E.false (5)if ef goto E.true (6)goto E.false,例:if ab or cd and ef then S1 else S2的翻译:,(1)if ab goto 7 (2)go
22、to 3 (3)if cd goto 5 (4)goto p+1 (5)if ef goto 7 (6)goto p+1 (7)(关于S1的四元式) (p)goto q (p+1) (关于S2的四元式) (q),回填地址: 拉链返填,(10) goto E.true (20) goto E.true (30) goto E.true 则链成 (10) goto (0) (20) goto (10) (30) goto (20),布尔表达式的控制流翻译,翻译中所用函数: E.true和E.false分别表示真链和假链; nextstat:指向下一个四元式地址; emit:产生四元式; merge
23、(p1,p2):将p1和p2为链首的两条链合并为1条; backpatch(p,t):把p所链接的每个四元式的第4段都填为t; E.codebegin:表示表达式E的第一个四元式语句序号;,布尔表达式的控制流翻译,E E1 or E2 backpatch(E1.false, E2.codebegin) E.Codebegin := E1.codebegin; E.true := merge(E1.true, E2.true) E.false:=E2.false ,布尔表达式的控制流翻译,E E1 and E2 backpatch(E1.true, E2.codebegin) E.Codebeg
24、in := E1.codebegin; E.true := E2.true E.false:=merge(E1.false, E2.false) ,布尔表达式的控制流翻译,E not E1 E.true = E1.false;E.codebegin = E1.codebegin E.false = E1.true; ,布尔表达式的控制流翻译,E (E1 ) E.true = E1.true;E.codebegin = E1.codebegin E.false = E1.false; ,布尔表达式的控制流翻译,E true E.true := nextstat; E.codebegin = ne
25、xtstat emit(goto -)E false E.false := nextstat; E.codebegin = nextstat emit(goto -),例:再考虑布尔表达式ab or cd and ef的翻译:,100:if ab goto _ 101: goto _ 102: if cd goto _ 103: goto _ 104: if ef goto _ 105: goto _,100:if ab goto _ 101: goto _ 102: if cd goto _ 103: goto _ 104: if ef goto _ 105: goto _,例:再考虑布尔表
26、达式ab or cd and ef的翻译:,100:if ab goto _ 101: goto _ 102: if cd goto _ 103: goto _ 104: if ef goto _ 105: goto _,100:if ab goto _ 101: goto _ 102: if cd goto 104 103: goto _ 104: if ef goto _ 105: goto 103,100:if ab goto _ 101: goto _ 102: if cd goto _ 103: goto _ 104: if ef goto _ 105: goto _,例:再考虑布尔
27、表达式ab or cd and ef的翻译:,100:if ab goto _ 101: goto _ 102: if cd goto _ 103: goto _ 104: if ef goto _ 105: goto _,100:if ab goto _ 101: goto _ 102: if cd goto 104 103: goto _ 104: if ef goto _ 105: goto 103,100:if ab goto _ 101: goto _ 102: if cd goto _ 103: goto _ 104: if ef goto _ 105: goto _,100:if
28、 ab goto _ 101: goto 102 102: if cd goto 104 103: goto _ 104: if ef goto 100 105: goto 103,主要内容,中间代码的形式 简单赋值语句的翻译 布尔表达式的翻译 控制结构的翻译 说明语句的翻译 数组和结构的翻译,说明语句的翻译,最简单的说明句的语法: integernamelistrealnamelist namelistnamelist,idid 对这种说明语句的翻译是在符号表中登录该名和性质; 用自下而上翻译 存在问题:所有namelist归约后才能将他们的性质登记到符号表中; 文法改写: 1,idinte
29、ger id | real id,(1)integer identer(id,int);D.att:=int (2)real identer(id,real);D.att:=real (3) ,identer(id,att);D.att:=att,说明语句的翻译,过程中的说明语句 用全程变量offset表示变量在本过程的数据区的相对位置,增加的量为数据对象的宽度,用属性width表示.,real identer(id,real,offset);D.att:=real;D.width:=8; offset:=offset+D.width,说明语句的翻译,说明语句的翻译,有嵌套过程的程序,需指明保
30、存作用域的信息;,主要内容,中间代码的形式 简单赋值语句的翻译 布尔表达式的翻译 控制结构的翻译 说明语句的翻译 数组和结构的翻译,控制结构的翻译,翻译的主要思路: 分析程序语言,写出其文法; 根据文法,分析其生成的中间代码; 根据最终的中间代码,写出各产生式的翻译规则;,控制结构的翻译,条件转移 开关语句 for循环语句 出口语句 goto语句 过程调用语句,条件转移,文法: S if E then S1| if E then S1 else S2| while E do S1| begin L end| AL L;S|S 各非终结符符号的意义: S语句 L语句串 A赋值语句 E布尔表达式,
31、E.false,控制语句的结构翻译,控制语句,S,if E then S,1,E,的代码,E,.true,E,.true:,S,1,的代码,E.false:,中间代码生成:if E goto E.truegoto E.false E.true: S E.false: ,S,1,2,E,的代码,E,E,S,1,的代码,2,的代码,中间代码生成:if E goto E.truegoto E.false E.true: S1goto S.next E.false: S2 S.next: ,E.false,控制语句的结构翻译,控制语句,S,1,E,的代码,E,.true,E,S,1,的代码,中间代码生
32、成: S.begin: if E goto E.truegoto E.false E.true: S1goto S.begin E.false: ,条件转移,回填: S.chain和L.chain 文法改写: S if E then S1| if E then S1 else S2| while E do S1| begin L end| AL L;S|S,条件转移,改写后的文法: S CS1| Tp S2| Wd S1| begin L end| AL LS S1|S2C if E then Tp CS else Wd W E do Wwhile LS L;,条件转移,S if E then
33、 S1S CS1 S.chain := merge(C.chain,S1.chain) C if E then backpatch(E.true,nextstat)C.chain := E.false,中间代码生成:if E goto E.truegoto E.false E.true: S E.false: ,条件转移,S if E then S1 else S2 S Tp S2 S.chain := merge(Tp.chain, S2.chain) Tp CS else q := nextstatemit(GOTO -)backpatch(C.chain, nextstat)Tp.cha
34、in := merge(S.chain.q) C if E then backpatch(E.true,nextstat)C.chain := E.false,中间代码生成:if E goto E.truegoto E.false E.true: S1goto S.next E.false: S2 S.next: ,条件转移,S while E do S1 S Wd S1 backpatch(S1.chain, Wd.codebegin)emit(GOTO, Wd.codebegin)S.chain := Wd.chain Wd W E do backpatch(E.true, nextsta
35、t)Wd .chain := E.false;Wd .codebegin := W.codebegin Wwhile W.codebegin := nextstat,中间代码生成: S.begin: if E goto E.truegoto E.false E.true: S1goto S.begin E.false: ,条件转移,S begin L end S.chain := L.chain| A S.chain :0L LS S1 L.chain := S1.chain|S2 L.chain := S2.chain LS L; backpatch(L.chain, nextstat),条
36、件转移,while (AB) do if(CD) then X:=Y+Z,开关语句的翻译,开关语句: switch E ofcase V1: S1case V2: S2. . .case Vn - 1: Sn 1default: SnendE是一个表达式,也称为选择子;,开关语句的翻译,分支数较少时t = E的代码 L1: if t != V1 goto L2 S1的代码 goto next L2: if t != V2 goto L3 S2的代码goto nextL2: . . . . .,Ln-1: if t != Vn-1 goto LnSn -1的代码 goto next Ln: Sn
37、的代码 next:,开关语句的翻译,分支较多时t = E的代码 | Ln: Sn的代码goto test | goto next L1: S1的代码 |test: if t = V1 goto L1 goto next | if t = V2 goto L2 L2: S2的代码 | . . .goto next | if t = Vn-1 goto Ln-1. . . | goto Ln Ln-1: Sn -1的代码 | next: goto next,也可建立一个n项的二元组表;,开关语句的翻译,中间代码增加一种case语句,便于代码生成器 对它进行特别处理 (case, V1 , L1 ,
38、 -) (case, V2 , L2 , -) . . .(case, Vn-1 , Ln-1 , -) (case, t , Ln , -) (Label, next ,-, -),For循环语句的翻译,一般形式: for i:=E1 step E2,until E3 do S 等价于: i := E1; Goto OVER; AGAIN: i:=i+E2; OVER: if i=E3 then Begin S1; goto AGAIN end; 按如上顺序产生文法,需改写文法: F1 for i:=E1 F2 F1 step E2 F3 F2 until E3 S F3 do S1,For
39、循环语句的翻译,文法: F1 for i:=E1 emit(entry(i), :=, E1.place);F1.place := entry(i);F1.chain := nextstat;emit (goto,-);F1.codebegin := nextstat;| F2 F1 step E2 F2.codebegin := F1.codebegin;F2.place := F1.place;emit(F1.place := E2.place, + F1.place);backpatch(F1.chain, nextstat);| F3 F2 until E3 S F3 do S1,Fo
40、r循环语句的翻译,文法: F3 F2 until E3 F3.codebegin := F2.codebegin;q := nextstat;emit(if F2.place, = E3.place, goto. q+2);F3.chain := nextstat;emit(goto -);| S F3 do S1 emit(goto. F3.codebegin);backpatch(S1.chain, F3.codebegin);S.chain := F3.chain;,For循环语句的翻译,不同语言for语句语法与语义不尽相同 如: i := E1; Incr := E2; limit :
41、= E3; goto OVER; AGAIN: I := i+incr; OVER: if i=limit then begin S; goto AGAIN end;,出口语句的翻译,出口语句: Exit语句; Break语句; 难点: 需要通过回填技术给出转移目标;,出口语句,参见课本P193,Goto语句,主要语句: goto L 和L : S 情形一: L:S 在符号表中登记L的项的”地址”栏中登记语句D的第一个四元式的地址 goto L (j,-,-,p) 情形二: goto L (goto -) L: S 回填goto的转移目标 使用回填技术(参见图8.20),定义标号语句的产生式,
42、S S i: 那么,当用i:进行归约时,应做如下的语义动作: 1.若i所指的标识符(假定为L)不在符号表中,则把它填入,置“类型”为“标号”,“定义否”为“已”,“地址”为nextstat。 2.若已在符号表中但“类型”不为“标号”或“定义否”为“已”,则报告出错。 3.若已在符号表中,则把标志“未”改为“已”,然后,把地址栏中的链首(设为)取出,同时把nextstat填在其中,最后,执行backpatch(,nextstat)。,翻译语句时,还有两点必须注意,第一:相同名字的标号可以在不同名字作用域中定义。如: () () : () ;/延迟使用 () () : () () ,第二,转移标号
43、是非法的,()for = to 10 do () begin goto; () for = to 20 do () begin goto ; () L: end forend for i 处理到第()行后,第()行的goto目标得以解决。而第()行的goto 是非法的,但只有当循环关闭时才能确定。,过程调用的四元式产生,过程调用的实质是把程序控制转移到子程序(过程段)。在转子之前必须用某种办法把实在参数的信息传给被调用的子程序,并且应该告诉子程序在它工作完毕后返回到什么地方。 传递实在参数 , 过程调用 (, ) 将被翻译成: 计算置于中的代码 = 第一个实参地址 第二个实参地址 转子指令,如
44、何产生反映这种模式的四元式,过程调用语句的文法: ()Scall (arglist) (),E ()E定义arglis.queue,称作队列,记录每个实在参数的地址;,arglist.QUEUE 在处理实在参数串的过程中记住每个实参的地址,()Scall (arglist)For 队列 argulist.QUEUE 的每一项 DoGen(par _,_,p);Gen(call,_,_,entry(i)(),E 把.PLACE 排在arglist .QUEUE 的末端;arglist.QUEUE:= arglist .QUEUE ()E 建立一个arglist.QUEUE ,它只包含一项E.PL
45、ACE,主要内容,中间代码的形式 简单赋值语句的翻译 布尔表达式的翻译 控制结构的翻译 说明语句的翻译 数组和结构的翻译,数组和结构的翻译,数组说明和数组元素的引用翻译 结构(记录)说明和引用的翻译,数组说明和数组元素的引用翻译,相关定义: 数组:同一类型数据所组成的某种n维矩形结构; 下标:沿着每一维的距离; 下标元素:数组的每个元素; 数组的每个元素是矩形结构中的一个点,它的位置可以通过每维的下标来确定; 确定数组(静态数组):数组所需的存储空间的大小在编译时已知道; 可变数组(动态数组):数组所需的存储空间的大小在编译时未知;,数组说明和数组元素的引用翻译,数组的存储方式: 按行存放(参
46、见P198图8.22) 按列存放(参见P198图8.23),数组说明和数组元素的引用,内情向量: 确定数组:编译时确定; 可变数组:运行时,专门定义一个子程序负责建立内情向量并分配数组空间;,将产生两组计算数组元素地址的四元式 一组计算,将它放在某个临时单元中; 一组计算,放在另一个临时单元T1中。 对应“数组元素引用”(引用其值)和“对数组元素赋值”有两个相应的四元式:“变址取数”和“变址存数”。“变址取数”的四元式是: ( , T1 T ,)相当于= T1 T “变址存数”的四元式是: ( , , T1 T )相当于T1 T :=x,数组说明和数组元素的引用,数组说明和数组元素的引用翻译,例 X:=AI,J例AI+2,J+1:=M+N,结构(记录)说明和引用的翻译,结构(记录) 定义:由已知类型的数据组合起来的一种数据类型; 实例: struct dataint day;char month-name4;int year; ;,结构(记录)说明和引用的翻译,