2012-2013学年中科大本科编译原理期末试卷-参考解答

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

(2) 直接在该 C 源程序上进行循环优化(包括循环不变计算外提,强度消弱等) 。 (10 分) 参考答案在最后! 7 针对所给的 C 程序: 描述运行时函数 main 和 func 的活动记录, 并由此解释程序的输出为何。 (5 分) #include <stdio.h> void func(char *s){ s = (char*)malloc(10); }// 第 7 题 C 程序
该程序输出为 error。因为,main 调用 func 的传参方式为值调用,即仅将指针 p 的 值 NULL 传入 s 形参单元。这样,形参 s 做的任何改变均不会对实参 p 有影响,故而 p 保持 NULL 值。 计算机学院 2010 级本科编译原理期终考试卷
2/2
8
针对如下 C 程序及其汇编代码(片段) : (5 分) (1) 补全下划线处的空白汇编代码; (2) 描述所用编译器对 C 分程序所声明变量的存储分配策略; (5 分) .LC0: .long 0 .long 1 .long 2 .long 3 .long 4 .long 5 .LC1: .string "%d\n" .text .globl main .type main,@function main: pushl %ebp movl %esp, %ebp pushl %edi pushl %esi subl $48, %esp andl $-16, %esp movl $0, %eax subl %eax, %esp leal -40(%ebp), %edi movl $.LC0, %esi cld movl $6, %eax movl %eax, %ecx rep movsl movl $6, -44(%ebp) movl $7, -48(%ebp) leal -40(%ebp), %eax addl movl %eax, -52(%ebp) subl $8, %esp movl -52(%ebp), %eax subl $ , %eax pushl pushl $.LC1 call printf addl $ , %esp movl $0, %eax leal , %esp popl %esi popl %edi leave ret //第 9 题 汇编代码片段
2 说明以下文法 G1 为 LR(1)的,但不是 LALR(1)的,也不是 SLR(1)的。 (15 分) S 是开始符号。 S → A a | b A c | B c | b B a A → d B → d
计算机学院 2010 级本科编译原理期终考试卷
1/2
解: G1 仅产生串 da、bdc、dc 和 bda。 读入活前缀 d 后到达的 LR(1)项目集簇为: 状态 i:{A → d.,a ; B → d.,c} 读入活前缀 bd 后到达的 LR(1)项目集簇为: 状态 j:{A → d.,c ; B → d.,a} 显然, 在构造的 LR(1)项目集簇中不存在移进-归约或归约-归约冲突。 因此, 该文法为 LR(1) 的。而上述状态 i 和 j 为同心集,合并后为{A → d.,a/c ; B → d.,a/c},则出现了新 的归约-归约冲突,而这个冲突在合并前是没有的。因此,该文法不是 LALR(1)的。 很明显,该文法也不是 SLR(1)的,因为在读入活前缀 d 后到达的 LR(0)项目集簇(状态) 为{A → d. ; B → d. },包含了两个归约项目,而 follow(A)∩follow(B)={a,c} ≠Φ,因此,存在归约-归约冲突,故而该文法不是 SLR(1)的。 (10 分) 3 以下文法 G2 是否为 LL(1)的?如不是,适当修改该文法,使之成为 LL(1)的。 A 是开始符号。 A → B a B → d a b B → C b C → c B C → A c 解: 显然该文法含有左递归:A=>B a=>C b a=>A c b a。因此该文法不是 LL(1)的。 文法修改过程如下: C → B a c A 带入 C,得到 C → c B C 带入 B,得到 B → d a b | c B b | B a c b 消除 B 的直接左递归: B → d a b E | c B b E E → a c b E E → 注:此为空产生式 可知 B 产生串:(dab|cBb)(acb)* 而 A 产生的串:(dab|cBb)(acb)*a = (dab|cBb)a(cba)* 因此,可重新给出的 A 的产生式如下:(重写 A 的串组成方式,主要消除原来 Follow(B) 中含 a 的情况,否则在 E 的两个产生式均出现在 a 的名下,而那样不符合 LL(1)文法要求! ) A → d a b a D | c B b a D D → c b a D D → 注:此为空产生式 最终修改后的文法如下,满足 LL(1)文法特征: A → d a b a D | c B b a D D → c b a D D → 注:此为空产生式 B → d a b E | c B b E E → a c b E E → 注:此为空产生式 计算机学院 2010 级本科编译原理期终考试卷
100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 j=0 if j >= 10 goto 132 t1 = i * 10 t1 = t1 + j t2 = t1 * 4 t3 = d[t2] t4 = i * 10 t4 = t4 + k t5 = t4 * 4 t6 = d[t5] t7 = k * 10 t7 = t7 + j t8 = t7 * 4 t9 = d[t8] t10= t6 + t9 if t3 > t10 goto 117 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 goto 130 t11 = i * 10 t11 = t11 + j t12 = t11 * 4 t13 = i * 10 t14 = t13 + k t15 = t14 * 4 t16 = d[t15] t17 = k * 10 t17 = t17 + j t18 = t17 * 4 t19 = d[t18] t20 = t16 + t19 d[t12] = t20 j=j+1 goto 101
计算机学院 2010 级本科编译原理期终考试卷
1/2
ቤተ መጻሕፍቲ ባይዱ
#include <stdio.h> int main() { int a[6]={0,1,2,3,4,5}; int i=6,j=7; int *p = (int*)(&a+1); printf("%d\n",*(p-1)); return 0; } //第 9 题 C 程序 9 仔细阅读所给 C 程序及其汇编代码片段。 (1) 指出波浪线处的汇编代码的作用; (5 分) 解:该汇编代码序列的作用,就是给局部数组 a 赋初值。 (2)补全下划线处的空白汇编代码。 (5 分) 解:空白处汇编代码如下: addl $24,%eax
解: (1) 空白处汇编代码如下: movl %esp, %ebp movl $0, -4(%ebp) movl $0, -8(%ebp) movl $1, -12(%ebp) movl $3, -16(%ebp) (2) 将分程序中声明的局部变量与函数 (或过程)定义的局部变量统一分配存储; 那些生存期相互独立的分程序中的局部 变量将共享存储位置。
0 1 0 1 0 1
6 针对如下 C 程序片段: int d[10][10]; for(int k = 0; k < 10; k++) for(int i = 0; i < 10; i++)
计算机学院 2010 级本科编译原理期终考试卷
1/2
for(int j = 0; j < 10; j++) if(d[i][j] > d[i][k] + d[k][j]) d[i][j] = d[i][k] + d[k][j]; (1) 给出最内层 j 循环的三地址代码; (10 分) 解: 假设三地址代码从 100 开始编号:
5 针对以下文法 G3,写一个翻译方案,输出所接受的二进制串的十进制值。 当输入串为空时,则输出的值为 0。如需要,可添加新的开始符号 S 及产生式 S→D,但不 得修改其他产生式。 (10 分) D 是开始符号。 D → 注:此为空产生式! D → 0 D D → 1 E E → 0 F E → 1 D F → 0 E F → 1 F 解: 为 D、E 和 F 引入继承属性 i,表示(在读新串前)已读入二进制串的值; 引入综合属性 s,表示(读入新串后)所有读入的二进制串的值 翻译方案如下: S→ D → D → D → E → E → F → F → { D.i { D.s {D 1 .i {E.i {F.i {D.i {E.i {F 1 .i := 0; } := D.i; } := D.i * 2; } := D.i * 2 + 1;} := E.i * 2; } := E.i * 2 + 1;} := F.i * 2; } := F.i * 2 + 1;} D {print(D.s);} 注:此为空产生式! D 1 {D.s := D 1 .s;} E {D.s := E.s;} F {E.s := F.s;} D {E.s := D.s;} E {F.s := E.s;} F 1 {F.s := F 1 .s;}
#include <stdio.h> int main() { int a=0, b = 0; { int a = 1; } { int b = 2; { int a = 3; } } return 0; } //第 8 题 C 程序 main: pushl %ebp subl $24, %esp andl $-16, %esp movl $0, %eax subl %eax, %esp movl $0, movl $0, movl $1, movl $2, -12(%ebp) movl $3, movl $0, %eax leave ret //第 8 题 汇编代码片段
int main() { char *p = NULL; func(p); if(!p)printf("error\n"); else printf("ok\n"); return 0; }// 第 7 题 C 程序
解:main 函数与 func 函数的活动记录的主要内容安排如下: 返回地址 调用者 bp 局部变量 p main 活动记录 bp 形参 s 返回地址 调用者(main)bp func 活动记录 bp
中 国 科 学 技 术 大 学 2012-2013 学年第一学期考试试卷 参考解答
考试科目: 编译原理与技术 学生所在系: 姓名: 得分: 学号:
1 给出识别正规式 01(((10)*| 111)* | 0 )* 1 的极小化 DFA M 的构造过程。 (10 分) 解: (1)识别该正规式的 NFA 如下: 0 1 1 3 0 1 1 1 4 5
2/2
4 针对未修改的文法 G2 中,写一个语法制导定义,可打印输入串中 a 的个数。 (10 分) 解: 可以考虑添加新的开始符号 S 及产生式 S→A,但不得修改其他产生式。 引入属性 A.a、B.a 和 C.a 表示相应串中的 a 的个数。 产生式 S→A A → B a B → d a b B → C b C → c B C → A c 语法制导定义 print(A.a) A.a:= B.a + 1 B.a := 1 B.a := C.a C.a := B.a C.a := A.a
0
1
2 0
识别正规式的 NFA (2)然后,采用子集构造法,给出识别该正规式的 DFA,如下:
输入 状态子集 {0} {1} {2} {3,5} {4}
0 {1} ―― {2} {2} ――
1 ―― {2} {3,5} {4} {2}
(3)最后,再极小化该 DFA。最终的状态子集划分为:{0}、 {{1}和{4}} 、{2}和{3,5} 因此,极小化 DFA M 如下: 0 0 0 1 1 2 1 1 0 3
相关文档
最新文档