编译原理 陈意云 课后答案

合集下载

编译原理陈意云课后答案.ppt

编译原理陈意云课后答案.ppt

5
3.2
• 考虑文法 S -> aSbS|bSaS|ε (a) 为句子abab构造两个不同的最左推导, 以说明此文法二义 (b) 为abab构造对应的最右推导 (c) 为abab构造对应的分析树 (d) 这个文法产生的语言是什么
2019/3/22
luanj@
6
3.2 (续)
luanj@ 9
2019/3/22
3.4 (续)
• 该文法没有体现运算符 |、*、() 、并置的优 先级,因而是二义的。
R=>R|R=> a|R =>a|R*=>a|b* R=>R*=>R|R*=>a|R*=>a|b*
• E -> E’|’T | T T -> TF | F F -> F* | (E) | a | b
• (1) S=>aSbS=>abS=>abaSbS=>ababS=>abab (2) S=>aSbS=>abSaSbS=>abaSbS=>ababS=>abab • S=>aSbS=>aSb=>abSaSb=> abSab =>abab (2)
S a S ε b a S ε (1) 描述的语言是a,b数目相等的串 S b S ε S
S
( L S a L , ( L S a
2019/3/22 luanj@ 3
) S L , ) S a
3.1 (续) - (a,((a,a),(a,a)))
S =>(L) =>(L,S) =>(S,S) =>(a,S) =>(a,(L)) =>(a,(L,S)) =>(a,(S,S)) =>(a,((L),S)) =>(a,((L,S),S)) =>(a,((S,S),S)) =>(a,((a,S),S)) =>(a,((a,a),S)) =>(a,((a,a),(L))) =>(a,((a,a),(L,S))) =>(a,((a,a),(S,S))) =>(a,((a,a),(a,S))) =>(a,((a,a),(a,a))) S =>(L) =>(L,S) =>(L,(L)) =>(L,(L,S)) =>(L,(L,(L))) =>(L,(L,(L,S))) =>(L,(L,(L,a))) =>(L,(L,(S,a))) =>(L,(L,(a,a))) =>(L,(S,(a,a))) =>(L,((L),(a,a))) =>(L,((L,S),(a,a))) =>(L,((L,a),(a,a))) =>(L,((S,a),(a,a))) =>(L,((a,a),(a,a))) =>(S,((a,a),(a,a))) =>(a,((a,a),(a,a)))

中国科学技术大学陈意云编译原理全套参考资料chapter4

中国科学技术大学陈意云编译原理全套参考资料chapter4

中国科学技术大学陈意云编译原理全套参考资料chapter4中国科学技术大学陈意云编译原理全套参考资料chapter4 第四章语法制导的翻译在3.7节用Yacc写的例子中,我们看到一种有用的描述形式:语言结构的属性附加在代表语言结构的文法符号上,这些属性值由附加在文法产生式的语义动作来计算,这些语义动作在归约对应的产生式时进行计算,由此得到结果。

这种描述形式可用来描述编译器的语义分析,因此本章系统地研究这种称之为“语法制导下的语言翻译”的描述方法及其实现。

它的语义动作(有时称为语义规则)的计算可以产生代码、把信息存入符号表、显示出错信息、或完成其它工作。

语义规则的计算结果就是我们所要的记号流的翻译。

本章讨论语义规则和产生式相联系的两种方式:语法制导的定义和翻译方案。

语法制导定义是较抽象的翻译说明,它隐蔽了一些实现细节;而翻译方案陈述了一些实现细节,主要是指明了语义规则的计算次序。

在第五章说明语义检查和第七章描述中间代码生成时,大量使用这两种方法。

本章还讨论语法制导定义和翻译方案的实现方法。

概念上的方法是,首先分析输入的记号串,建立分析树,然后从分析树得到描述结点属性间依赖关系的有向图,从这个依赖图得到语义规则的计算次序,然后进行计算,最终得到翻译的结果。

实际的实现并不需要按上面步骤逐步进行,本章将讨论几种不同限制下的实现方法。

4.1 语法制导的定义语法制导的定义是上下文无关文法的推广,其中每个文法符号都有一个属性集合,它分成两个子集,分别叫做该文法符号的综合属性集合和继承属性集合。

如果我们把分析树上的结点看成是保存对应文法符号的属性的记录,那么属性对应记录的域。

属性可以表示任何东西:串、数、类型、内存单元,或其它想表示的东西。

分析树结点的属性值由该结点所用产生式的语义规则定义。

在语法制导定义中,我们把其中的文法称为基础文法。

本节介绍语法制导定义的形式及其概念上的实现模型。

4.1.1 语法制导定义的形式在语法制导定义中,每个文法符号有一组属性,每个文法产生式A , ,有一组形式为b := f (c, c, …, c )的语义规则,其中f 是函数,b和c, c, …, c 是该产生式的文法符号的12k12k属性,并且:(1) 如果b是A的属性,c , c , …, c 是产生式右部文法符号的属性或A的其它属12k性,那么b叫做文法符号A的综合属性。

编译原理课后习题答案

编译原理课后习题答案

编译原理课后习题答案第一章1.典型的编译程序在逻辑功能上由哪几部分组成?答:编译程序主要由以下几个部分组成:词法分析、语法分析、语义分析、中间代码生成、中间代码优化、目标代码生成、错误处理、表格管理。

2. 实现编译程序的主要方法有哪些?答:主要有:转换法、移植法、自展法、自动生成法。

3. 将用户使用高级语言编写的程序翻译为可直接执行的机器语言程序有哪几种主要的方式?答:编译法、解释法。

4. 编译方式和解释方式的根本区别是什么?答:编译方式:是将源程序经编译得到可执行文件后,就可脱离源程序和编译程序单独执行,所以编译方式的效率高,执行速度快;解释方式:在执行时,必须源程序和解释程序同时参与才能运行,其不产生可执行程序文件,效率低,执行速度慢。

第二章1.乔姆斯基文法体系中将文法分为哪几类?文法的分类同程序设计语言的设计与实现关系如何?答:1)0型文法、1型文法、2型文法、3型文法。

2)2. 写一个文法,使其语言是偶整数的集合,每个偶整数不以0为前导。

答:Z→SME | BS→1|2|3|4|5|6|7|8|9M→ε | D | MDD→0|SB→2|4|6|8E→0|B3. 设文法G为:N→ D|NDD→ 0|1|2|3|4|5|6|7|8|9请给出句子123、301和75431的最右推导和最左推导。

答:N?ND?N3?ND3?N23?D23?123N?ND?NDD?DDD?1DD?12D?123N?ND?N1?ND1?N01?D01?301N?ND?NDD?DDD?3DD?30D?301N?ND?N1?ND1?N31?ND31?N431?ND431?N5431?D5431?7 5431N?ND?NDD?NDDD?NDDDD?DDDDD?7DDDD?75DDD?754 DD?7543D?75431 4. 证明文法S→iSeS|iS| i是二义性文法。

答:对于句型iiSeS存在两个不同的最左推导:S?iSeS?iiSesS?iS?iiSeS所以该文法是二义性文法。

5编译原理,陈意云 ,课后答案5

5编译原理,陈意云 ,课后答案5

10
7.5 (续) (续
• (a) *a-+bc • (c) 表达式翻成前缀形式的语法制导定义
E -> E+T | T T -> T*F | F F -> -F | (E) | id L -> En { printf(E.string); } E -> E1 + T { E.string = “+” + E1.string + T.string; } E -> T { E.string = T.string; } T -> T1*F { T.string = “*” + T1.string + F.string; } T -> F { T.string = F.string; } F -> -F1 { F.string = “-” + F1.string; } F -> (E) { F.string = E.string; } F -> id { F.string = id.value; }
2011-3-28
luanj@
8
7.4 (续) (续
• D -> ID_LIST:T ID_LIST -> ID_LIST,ID_LIST|id • D -> { Init(idtable) } ID_LIST:T { for each name in idtable do enter(name, T.type, offset); offset := offset + T.width; end; } ID_LIST -> { Init(idtable1); Init(idtable2) } ID_LIST1,ID_LIST2 { merge(idtable1, idtable2, idtable) } ID_LIST -> id { add(idtable, ); }

编译原理陈意云_课后答案2.

编译原理陈意云_课后答案2.

2021/4/13
luanj@
22
3.15
• (a) 用3.1的文法构造(a,(a,a))的最右推导, 说出每个右句型的句柄
• (b) 给出对应(a)的最右推导的移进-归约分 析器的步骤
• (c) 对照(b)的移进-归约,给出自下而上构 造分析树的步骤。
2021/4/13
➢ 期望的是: if expr then if expr then matched_stmt else if expr then matched_stmt else stmt
2021/4/13
luanj@
13
3.5 (续)
• 一种推导,和期望的不一样
➢ stmt
=> matched_stmt => if expr then matched_stmt else stmt => if expr then if expr then matched_stmt else stmt else stmt => if expr then if expr then matched_stmt else if expr then stmt else stmt => if expr then if expr then matched_stmt else if expr then matched_stmt else stmt
2021/4/13
luanj@
S
( L) L,S
S ( L)
aL
,
S
S
( L)
( L) L , S
L , SS
a
S
aa
4
a
3.1 (续)
• 描述的语言: 括号匹配的串,串中的各项由”,”隔开,

5编译原理,陈意云 ,课后答案5

5编译原理,陈意云 ,课后答案5

2019/2/12
luanj@
8
7.4 (续)
• D -> ID_LIST:T ID_LIST -> ID_LIST,ID_LIST|id • D -> { Init(idtable) } ID_LIST:T { for each name in idtable do enter(name, T.type, offset); offset := offset + T.width; end; } ID_LIST -> { Init(idtable1); Init(idtable2) } ID_LIST1,ID_LIST2 { merge(idtable1, idtable2, idtable) } ID_LIST -> id { add(idtable, ); }
编译原理习题课(5)
栾 俊 luanj@ 2019/2/12
7.1
• 把算术表达式 –(a+b)*(c+d)+(a+b-c) 翻译成: (a) 语法树 (b) 有向无环图 (c) 后缀表示 (d) 三地址代码
2019/2/12
luanj@
{ enter(, T.type, offset); offset += T.width; } { T.type = integer; T.width = 4; } { T.type = real; T.width = 8; } { T.type = array(num.val, T1.type); T.width = num.val * T1.width; } { T.type = pointer(T1.type); T.width = 4; }
2019/2/12 luanj@ 11

编译原理部分课后答案,仅供参考

编译原理部分课后答案,仅供参考

第一章编译程序概述1.1什么是编译程序编译程序是现代计算机系统的基本组成部分之一,而且多 数计算机系统都含有不止一个高级语言的编译程序。

对有些高 级语言甚至配置了几个不同性能的编译程序。

1.2编译过程概述和编译程序的结构编译程序完成从源程序到目标程序的翻译工作,是一个复 杂的整体的过程。

从概念上来讲,一个编译程序的整个工作过 程是划分成阶段进行的,每个阶段将源程序的一种表示形式转 换成另一种表示形式,各个阶段进行的操作在逻辑上是紧密连 接在一起的。

一般一个编译过程划分成词法分析、语法分析、 语义分析、中间代码生成,代码优化和目标代码生成六个阶段,这是一种典型的划分方法。

事实上,某些阶段可能组合在一起, 这些阶段间的源程序的中间表示形式就没必要构造岀来了。

我 们将分别介绍各阶段的任务。

另外两个重要的工作:表格管理 和岀错处理与上述六个阶段都有联系。

编译过程中源程序的各 种信息被保留在种种不同的表格里,编译各阶段的工作都涉及 到构造、查找或更新有关的表格,因此需要有表格管理的工作; 如果编译过程中发现源程序有错误,编译程序应报告错误的性 质和错误发生的地点,并且将错误所造成的影响限制在尽可能 小的范围内,使得源程序的其余部分能继续被编译下去,有些 编译程序还能自动校正错误, 这些工作称之为岀错处理。

图1.3表示了编译的各个阶段。

图1.3编译的各个阶段它不生成目标代码,它每遇到一个语句,就要对这个语句进行 分析以决定语句的含义,执行相应的动作。

右面的图示意了它 的工作机理第二章:PL/O 编译程序问答第1题 PL/0语言允许过程嵌套定义和递归调用,试问 它的编译程序如何解决运行时的存储管理。

答:PL/0语言允许过程嵌套定义和递归调用,它的编译程序在运行时采用了栈式动态存储管理。

(数组CODE 存放的只读目 标程序,它在运行时不改变。

)运行时的数据区S 是由解释程序 定义的一维整型数组,解释执行时对数据空间S 的管理遵循后进先岀规则,当每个过程(包括主程序)被调用时,才分配数据 空间,退出过程时,则所分配的数据空间被释放。

编译原理陈意云课后答案

编译原理陈意云课后答案

22.07.2020
luanj@
9
3.16 (续)
• Goto(I4, )) =
I6 S -> (L ) ∙
• Goto(I4, ,)=
I7 L -> L , ∙ S S -> ∙(L) S -> ∙a22.07.20来自0luanj@23
谢谢!!
22.07.2020
luanj@
19
3.26 (续)
I0 L’ -> ∙L, $ L -> ∙MLb, $ L -> ∙a, $ M -> ∙ , a
L I1 L’ -> L ∙, $
I2
M
L -> M ∙Lb, $ L -> ∙MLb, b
L -> ∙a, b
M -> ∙, a
• 只有直接左递归 S -> (L)|a L -> SL’ L’-> ,SL’|ε
22.07.2020
luanj@
3
3.8(b) (续)
• S -> (L)|a L -> SL’ L’-> ,SL’|ε
• FIRST(S) = {(, a} FIRST(L) = FIRST(S) = {(, a} FIRST(L’) = {,, ε}
➢S->aAc A->bAb|b
22.07.2020
luanj@
22
3.30 (续)
• 第二个不是LR(1)文法 第二个文法在句子的正中心按A->b规约, 而只向后看一位是无法判断是否到达句子 的中心位置的
• 存在冲突的项目集:
S -> a∙Ac, $ A -> ∙bAb, c A -> ∙b, c

编译原理(第2版)陈意云张昱编著课后答案

编译原理(第2版)陈意云张昱编著课后答案

Use as a study resource to enhance comprehension and retention of the material.
编译原理概述
1 Definition
Study of translating source code into machine-readable format.
A tool that performs lexical analysis by scanning and tokenizing the source code.
结论和要点
Key Takeaways
1. Understanding compilation principles is essential for software development.
3 Group Study
Collaborate with classmates to compare and discuss solutions.
第一章:引论
1
Introduction to Compilation
Overview of the compilation process and its importance.
2 Importance
Essential for understanding software development and building compilers.
3 Topics Covered
Lexical analysis, syntax analysis, semantic analysis, code generation, and optimization.
课后答案的使用方法
1 Reference Guide

编译原理,陈意云 ,课后答案3

编译原理,陈意云 ,课后答案3
• FIRST(S) = {(, a} FIRST(L) = FIRST(S) = {(, a} FIRST(L’) = {,, ε}
• FOLLOW(S) = (FIRST(L’)-{ε}) + FOLLOW(L) + FOLLOW(L’) + {$} = {,, ), $} FOLLOW(L) = {)} FOLLOW(L’) = FOLLOW(L) = {),$}
3.26
• 一个非LR(1)的文法如下: L -> MLb | a M -> ε
给出所有有移进-规约冲突的规范LR(1)项目 集
3.26 (续)
• 拓广文法: L’ -> L L -> MLb | a M -> ε
• I0
I0 L’ -> ∙L, $ L -> ∙MLb, $ L -> ∙a, $ M -> ∙ , $/a
3.8(a)
• (a) 消除3.1的左递归 (b) 在(a)的基础上构造LL(1)分析表
3.8(a) (续)
• S -> (L)|a L -> L,S|S
• 只有直接左递归 S -> (L)|a L -> SL’ L’-> ,SL’|ε
3.8(b) (续)
• S -> (L)|a L -> SL’ L’-> ,SL’|ε
• Goto(I2, S)=
I5 L -> S ∙
• Goto(I2, ()=I2 • Goto(I2, a)=I3
3.16 (续)
• Goto(I4, )) =
I6 S -> (L ) ∙
• Goto(I4, ,)=
I7 L -> L , ∙ S S -> ∙(L) S -> ∙a

编译原理(第2版)陈意云张昱编著课后答案

编译原理(第2版)陈意云张昱编著课后答案

DFA
22
3.7 构造等价于下列正规表达式的有限自动机.
(a) 10|(0|11)0*1
0
AD
1B
0
DD BC E
start A
1
0
E
E/
C 1
D
1
0
NFA
0 start A
1 BC E D /
0 D1
1
E
1
BC 0
DFA
23
(b) ((0|1)* |(11))*
0|1
B
start A

1 C
直接短语
是文法的句型(S * ) S * A且A 则是关于A的句型的直接短语.
句柄: 一个句型的最左直接短语称为句柄.
5
S ( L ) ( L, S ) ( S, S ) ( a, S ) ( a, ( L ))
短语 ( L ) L, S S
(e) 这个文法产生的语言是什么? a (a) (a,a) ((a,a),a) ...... a和数据元素为a的广义表全体
7
1.2 考虑文法
S aSbS | bSaS | (a) 试说明此文法是二义性的. (定义1.5) 如果一文法的句子存在两棵分析树, 则该句子是二义性的 . 如果一文法包含二义性的句子,则这个文法是二义性的.
1A
1
start S 0,1
1 C 0,1 f
0
0,1
0
B
0
状态转移图
图中状态C和f可合并, 得到左线性文法G’: C A1 | B0 | C1 | C0 A S1 B S0 S S0 | S1 |
左线性文法G’: f A1 | B0 | C1 | C0 A S1 B S0 C A1 | B0 | C1 | C0 S S0 | S1 |

编译原理课后作业参考答案

编译原理课后作业参考答案

作业参考答案第二章 高级语言及其语法描述6、(1)L (G 6)={0,1,2,......,9}+(2)最左推导:N=>ND=>NDD=>NDDD=>DDDD=>0DDD=>01DD=>012D=>0127 N=>ND=>DD=>3D=>34N=>ND=>NDD=>DDD=>5DD=>56D=>568 最右推导:N=>ND =>N7=>ND7=>N27=>ND27=>N127=>D127=>0127 N=>ND=>N4=>D4=>34N=>ND=>N8=>ND8=>N68=>D68=>568 7、G:S →ABC | AC | CA →1|2|3|4|5|6|7|8|9B →BB|0|1|2|3|4|5|6|7|8|9C →1|3|5|7|98、(1)最左推导:E=>E+T=>T+T=>F+T=>i+T=>i+T*F=>i+F*F=>i+i*F=>i+i*iE=>T=>T*F=>F*F=>i*F=>i*(E)=>i*(E+T)=>i*(T+T)=>i*(F+T)=>i*(i+T)=>i*(i+F)=>i*(i+i) 最右推导:E=>E+T=>E+T*F=>E+T*i=>E+F*i=>E+i*i=>T+i*i=>F+i*i=>i+i*iE=>T=>T*F=>T*(E)=>T*(E+T)=>T*(E+F)=>T*(E+i)=>T*(T+i)=>T*(F+i)=>T*(i+i)=>F*(i+i)=>i*(i+i) (2)9、证明:该文法存在一个句子iiiei 有两棵不同语法分析树,如下所示,因此该文法是二义的。

编译原理答案++陈意云+高等教育出版社

编译原理答案++陈意云+高等教育出版社

《编译原理》习题参考答案(一)Bug report: zpli@Or find: 电一楼二楼全球计算实验室李兆鹏第二章2.3 叙述由下列正规式描述的语言a) 0(0|1)*0b) ((ε|0)1*)*c) (0|1)*0(0|1)(0|1)d) 0*10*10*10*e) (00|11)*((01|10)(00|11)*(01|10)(00|11)*)*Answer:a)以0开始和结尾,而且长度大于等于2的0、1串b)所有0,1串(含空串)c)倒数第三位是0的0、1串d) 仅含3个1的0、1串e) 偶数个0和偶数个1的0、1串(含空串)2.4 为下列语言写出正规定义:f) 由偶数个0和偶数个1构成的所有0和1的串g) 由偶数个0和奇数个1构成的所有0和1的串Answer:标准答案见《编译原理习题精选》P1-P2 1.1&1.2题2.7 用算法2.4为下列正规式构造非确定的有限自动机,给出它们处理输入串ababbab的转换序列。

c)((ε|a)b*)*d)(a|b)*abb(a|b)*Answer:c)NFA:输入串ababbab 的转换序列:0 1456789 145678 789 1456789 10Or 0 1456789 1456789 1236789 1456789 10d) NFA:输入串ababbab 的转换序列:0 1236 1456 789 10 11 12 13 16 11 14 15 16 172.8 用算法2.2把习题2.7的NFA 变换成DFA 。

给出它们处理输入串ababbab 的状态转换序列。

Answer: //针对2.7 (c)3个不同的状态集合:A = {0, 1, 2, 3, 4, 6, 7, 9, 10}B = {1, 2, 3, 4, 5, 6, 7, 9, 10}C = {1, 2, 3, 4, 6, 7, 8, 9, 10} NFA 的转换表:输入符号状态a bA B C B B C C BC子集构造法应用于2.7(c)得DFA:2.11 我们可以从正规式的最简DFA同构来证明两个正规式等价。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

gcc2_compiled:
.data
.align 4
.type aa,@object
.size aa,4
aa:
--aa分配在静态数据区,作
用域为本文件,生存期为整个程序
.long 10 –aa静态置初值
.globl bb
--bb分配在静态数据区,作
用域为全局,可以被其他文件引用,
生存期为整个程序
.align 2
7
6.3 (续)
• #include <stdio.h> static struct _a{ char c1; long i; char c2; double f; } a = {'A', 1, 'B', 1.0};
• VC6下,Debug模式Memory窗口查看
|A
|1
|B
|1.0
|
• GCC: (GNU) 3.2.2 20030222 (Red Hat Linux 3.2.2-5)
.text .align 4 .globl func .type func,@function func: pushl %ebp movl %esp, %ebp subl $4, %esp movw $40, -2(%ebp) --dd分配在栈上,生存期为 func调用期,动态置初值 .L1: leave ret .Lfe1: .size func,.Lfe1-func .ident "GCC: (GNU) egcs-2.91.66 19990314/Linux(egcs-1.1.2 release)”
.type bb,@object
.size bb,2
bb:
.value 20 –bb静态置初值
.align 4
.type cc.2,@object
.size cc.2,4
cc.2: --cc分配在静态数据区,作用域为本文件, 生存期为整个程序。源程序中在函数内部,为防止 重名,需要重命名为cc.2
.long 30 –cc静态置初值
12.07.2020
luanj@
14
6.6 (续)
• C语言中,实参从右向左进栈,所以func(i1, i2, i3)按i3,i2,i1的顺序进栈
• 而j1,j2,j3按声明的顺序分配
12.07.2020
luanj@
15
6.7
• 下面的C程序中,printf的调用仅含格式控制 串,运行时输出3个参数,分析之 main(){ printf(“%d %d %d\n”); }
12.07.2020
luanj@
2
6.1 (续)
• with a a:=u b:=v with b a:=x b:=y
a—record a—a.a b—a.b b—record a—b.a b—b.b
12.07.2020
luanj@
3
6.2
• 考虑下面的C程序 main(){ char * cp1, * cp2; cp1 = “12345”; cp2 = “abcdefghij”; strcpy(cp1, cp2); printf(“cp1 = %s \n cp2 = %s \n”, cp1, cp2); }
该程序经以前的某些C编译器编译后,运行结果为: cp1 = abcdefghij cp2 = ghij
• 所以得到了三个不可预知值得整数。
12.07.2020
luanj@
17
6.8
• 下面给出一个C程序及其在X86/Linux下的编译结果。从结果看,func的四个局部变量i1, j1,f1,e1的地址间隔和他们的类型一致,而形参i,j,f,e的地址间隔和他们的类型 不一致,试分析原因
12.07.2020
luanj@
8
6.4
• 下面给出一个C程序及其在X86/Linux下的编译结 果,根据所生成的汇编程序来解释程序中4个变量 的存储分配、作用域、生成期和置初始值方式的 区别
static long aa = 10;
short bb = 20;
func(){
12.07.2020
cc.2: .long 30 .text .align 4
.globl func .type func,@function
func: pushl %ebp movl %esp, %ebp subl $4, %esp movw $40, -2(%ebp)
.L1: leave ret
func(i, j, f, e) short i, j; float f, e; {
short i1, j1; float f1, e1; printf(“Address of i, j, f,e = %o,%o,%o,%o\n”, &i, &j, &f, &e); printf(“Address of i1,j1,f1,e1 = %o,%o,%o,%o\n”, &i1, &j1, &f1, &e1); printf(“Address of short,int,long,float,double = %d,%d,%d,%d,%d\n”, sizeof(short), sizeof(int), sizeof(long), sizeof(float), sizeof(double)); } main(){ short i, j; float f, e; func(i, j, f, e); } 运行结果:
12.07.2020
luanj@
11
6.5
• 假定使用:(a)值调用;(b)引用调用;(c)值-结果调用;(d)换名 调用。下面程序的结果分别是什么?
program main(input, output); var a, b : integer; procedure p(x, y, z : integer); begin y := y + 1; z := z + x; end; begin a := 2; b := 3; p(a + b, a, a); print a; end.
• 换名调用 a := a+1; a := a+(a+b);
对形参的调用不改变实参的值,结果a 结果a为8 结果为7 结果为9
12.07.2020
luanj@
13
6.6
• 一个C程序如下: func(i1, i2, i3) long i1, i2, i3; { long j1, j2, j3; printf(“Address of i1 i2 i3 = %o,%o,%o\n”, &i1, &i2, &i3); printf(“Address of j1 j2 j3 = %o,%o,%o\n”, &j1, &j2, &j3); } main(){ long i1, i2, i3; func(i1, i2, i3); } 该程序在X86/Linux上运行结果为: Address of i1, i2, i3 = 27777775460,27777775464,27777775470 Address of j1, j2, j3 = 27777775444,27777775440,27777775434 从结果看func的3个形参地址逐渐升高,而3个局部变量地址逐渐降低。 试说明为什么
.Lfe1: .size func,.Lfe1-func .ident "GCC: (GNU) egcs-2.91.66
19990314/Linux(egcs-1.1.2 release)”
luanj@
10
6.4 (续)
.file "static.c“
.version “01.01”
12.07.2020
luanj@
6
6.3 (续)
• 数据对齐:为了寻址方便
• A: char long char
OXXX OOOO OXXX XXXX
double
OOOO OOOO
• B: char char long double
O OXX OOOO OOOO OOOO
12.07.2020
luanj@
12
6.5 (续)
• 值调用 x := 5; y := 2; z := 2; y := y + 1; z := z + x; 为2
• 引用调用 t := a + b; a = a + 1; a = a + t;
• 值-结果调用 t:=a+b; x:=t;y:=a;z:=a y:=y+1;z:=z+x; t:=x;a:=y;a:=z;
编译原理习题课(4)
栾俊 luanj@
12.07.2020
6.1
• 使用Pascal的作用域规则,确定下面程序中用于名字a,b 的每个出现的声明。程序输出整数1,2,3,4
program a (input output); procedure b (u, v, x, y : integer); var a : record a, b : integer end; b : record b, a : integer end; begin with a do begin a := u; b := v end; with b do begin a := x; b := y end; writeln (a.a, a.b, b.a, b.b) end; begin b(1, 2, 3, 4) end.
cp1
cp2
拷贝后结果为
a b c d e f g h i j \0 f g h i j \0
cp1
cp2
• 现代编译器编译通过,执行时会出错。(GCC: 段错误 / VC 非法访问)
相关文档
最新文档