精品编译原理复习题集docx.docx
《精品编译原理复习题集docx.docx》由会员分享,可在线阅读,更多相关《精品编译原理复习题集docx.docx(14页珍藏版)》请在冰豆网上搜索。
精品编译原理复习题集docx
《编译原理》复习题集
1•名词解释短语句柄文法上下文无关文法
LL
(1)文法
LR
(1)文法
语法分析
无环路有向图(DAG)
后缀式
语法制导翻译
遍
局部优化
词法分析
语法分析
语义分析
源语言
源程序
目标语言
中间语言(中间表示)
2.叙述下面的正规式描述的语言,并画岀接受该语言的最简DFA的状态转换图。
(1|01)*0*
3.Pascal语言无符号数的正规定义如下:
num—>digit(.digit)?
(E(+|-)?
digit)?
其中digit表示数字,用状态转换图表示接受无符号数的确定有限自动机。
4.画出Pascal中实数(不带正负号,可带指数部分)的状态转换图。
5.用状态转换图表示接收(a|b)*aa的确定的有限自动机。
6.处于/*和*/Z间的串构成注解,注解屮间没有*/。
画出接受这种注解的DFA的状态转换图。
7.某操作系统下合法的文件名为
device:
name.extension
其屮第一部分(device:
)和第三部分(.extension)可缺省,device,name和extension都是字母串,长度不限,但至少为1,画出识别这种文件名的确定有限自动机。
8.构造一个DFA,它接受2>{0,1}上0和1的个数都是偶数的字符串。
9.给出与下图的NFA等价的正规式。
10.把下面的NFA确定化。
11.下面两个文法屮哪一个不是LR
(1)文法?
对非LR
(1)的那个文法。
给出那个有移进一归约冲突的规范的LR
(1)项目集。
S-aAcAtbbA|b
S~》aAcAtbAb|b
12.将下面的DFA化成最简形式。
13.为语言
L={vv|vvg(a|b)*并且在w的任何前缀中,a的个数不少于b的个数}写一个LR
(1)文法,不准超过6个产生式。
14.写一个文法,使其语言是奇数集,且每个奇数不以0开头。
15.考查文法G(s):
S-*(T)a+Sa
T-T,S|S
⑴消除文法的左递归;⑵提取公共左因子;
⑶对每个非终结符,写岀不带冋朔的递归子程序。
16.设文法G(S):
S->(L)|aS|a
L->L,S|S
(1)消除左递归和冋溯;
(2)计算每个非终结符的FIRST和FOLLOW;
(3)构造预测分析表。
17・程序的文法如下:
PtD
£>T|id:
八procid;£>;S
(1)写一个语法制导定义,打印该程序一共声明了多少个id。
(2)写一个翻译方案,打卬该程序每个变量id的嵌套深度。
18.构造下面文法的LL
(1)分析表。
DtTL
Ttint|real
L—idR
Rt,idR|£
19.已知文法G(S)
S-a|A|(T)TTS|S写出句子((a,a),a)的规范归约过程及每一步的句柄。
20.已知文法G(E)
E-T|E+T
T->F|T*F
F->(E)|i
(1)给岀句型(T*F+i)的最右推导及画岀语法树;
(2)给出句型(T*F+i)的短语。
21・在PASCAL语言中,简单类型的变量的声明例举如下:
m,n:
integer
p,q,r:
real
为这样的声明写一个LR
(1)文法(为简单起见,变量标识符都用id表示),并根据你的文法写一个语法制导定义(或叫做为你的文法加上语义动作),它将变量的类型填入符号表。
22.一个非LR
(1)的文法如下:
LtMLb|a
M—>E
请给出所有有移进一归约冲突的LR
(1)项目集,以说明该文法确实不是LR
(1)的。
23.现有句型ybalfi和产生式ba,分别指出LL
(1)方法和LR
(1)方法在扫描到此句型的什么位置决定用此产生式?
24・
(a)为下面的算术表达式文法写一个语法制导的翻译方案,它将每个子表达式E的符号(即值大于零还是小于零)记录在属性E.sign中(属性值分别用POS或NEG表示)。
你可以假定所有的整数都不为零,这样就不用担心零的符号。
ETE*EI+E|-E|unsigned_integer
(b)为上面的表达式产生栈机器屁码。
代码执行后,表达式的值留在栈上。
你自己设计所需的栈机器指令,并写清楚指令的含义。
25.—个文法如下:
St(S)
S—»a
请给出该文法中对活前缀(((有效的LR
(1)项目。
26.为下面文法添加语义规则(或叫动作子程序),输出S'产生的二进制数的值,如输入是101时,输出5。
S'tS
StSB|B
Bt0|1
27.写岀表达式(a+b*c)/(a+b)-d的逆波兰表示及三元式序列。
28.何谓优化?
按所涉及的程序范围可分为哪几级优化?
29.目标代码有哪几种形式?
生成目标代码时通常应考虑哪几个问题?
30・把表达式
■(a+b)*(c+d)+(a+b+c)
翻译成三元式。
31.设布尔表达式的文法为
E-*EiVE2
E〜EiAE?
E->i
假定它们将用于条件控制语句屮,请
(1)改写文法,使之适合进行语法制导翻译;
(2)写出改写后的每个产生式的语义动作。
32.给出活动记录空间结构。
并给岀各部分的存储对象。
33•画出IFa>0THENx:
=x+lELSEx:
二4*(x-1)的翻译方案图。
34.—个C语言程序如下:
func(il,i2,i3)
longil,i2,i3;
{
longjl,j2,j3;
printf(^Addressesofil,i2,i3二%o,%o,%o\n〃,&il,&i2,&i3);printf(^Addressesofjl,j2,j3=%o,%o,%o\rT,&jl,&j2,&j3);
}
main()
{
longi1,i2,i3;
func(il,i2,i3);
}
该程序在SUN工作站上的运行结果如下:
Addressesofil,i2,i3二35777773634,35777773640,35777773644
Addressesofjl,j2,j3二35777773524,35777773520,35777773514从上面的结果可以看出,func函数的3个形式参数的地址依次升高,而3个局部变量的地址依次降低。
试说明为什么会有这个区别。
35.—个C语言程序如下:
voidfun(struct{intx;doubler;}val){}
main()
{
struct{intx;doubler;}val;
fun(val);
}
该程序在X86/Linux机器上的用cc命令编译时,报告的错误信息如下:
1:
warning:
structuredefinedinsideparms
1:
warning:
anonymousstructdeclaredinsideparameter1ist
1:
warning:
itsscopeisonlythisdefinitionordcclaration,
1:
warning:
whichisprobablynotwhatyouwant・
7:
incompatibletypeforargument1of'fun'
请问,报告最后一行的错误的原因是什么?
如何修改程序,使得编译时不再出现这个错误信息。
36.—个C语言程序如下:
main()
{
func();
printf(^Rcturnfromfunc\rT);
func()
chars[4];
strcpy(s,〃12345678〃);printf(〃%s\n〃,s);
}
该程序在PC机linux操作系统上的运行结果如下:
12345678
Segmentationfault(coredumped)
试分析为什么会岀现这样的运行错误。
37.—个C语言函数如下:
func(i)
longi;
{
longj;
j=i-l;
func(j);
}
该函数在PC机1irmx操作系统上编译生成的汇编代码如下:
・file"stack・c"
gcc2_compiled・:
_gnucompiledc:
.text
・align2
・globl_func
・type_func,©function
_func:
pushl%ebp
movl%esp,%ebp
subl$4,%esp
movl8(%ebp),%edx
decl%edx
movl%edx,-4(%ebp)
movl-4(%ebp),%eax
pushl%eax
call_func
addl$4,%esp
LI:
leave
ret
Lfel:
・size_func,Lfel-_func
试画出该函数的一个活动记录的内容,包括活动记录的每个单元存放什么东西、执行movl8(%ebp),%edx指令时栈顶指针所指的的位置、与活动记录有关的另一个指针所
指的位置和地址增长方向。
38.—个C语言的函数如下:
func(cj)
charc;longI;
{
func(c,l);
}
在X86/Linux机器上编译牛成的汇编代码如下:
.file"parameter.c"
.versionM01.01H
gcc2_compiled.:
.text
.align4
.globlfunc
.typefunc,@function
func:
pushl%ebp将老的基地址指针压栈
movl%esp5%ebp将当前栈顶指针作为基地址指针
subl$4,%esp分配空间
movl8(%ebp),%eaxmovb%al,-1(%ebp)movl12(%ebp),%eaxpushl%eaxmovsbl-1(%ebp),%eaxpushl%eaxcallfunc
addl$8,%esp
L1:
leave——和下一条指令一起完成恢复老的基地址指针,将栈顶ret——指针恢复到调用前参数压栈后的位置,并返回调用者
・Lfe1:
.sizefunc,.Lfe1・func
.ident"GCC:
(GNU)egcs-2.91.6619990314/Linux(egcs-1.1.2release)**
(a)请指出对应源程序第5行的函数调用func(c,l)的汇编指令是哪几条。
(b)请说明字符型参数和长整型参数在参数传递和存储分配方面有什么区别。
(小于长整型size的整型参数的处理方式和字符型参数的处理方式是一样的。
)
39.—个C语言程序及其在某种机器linux操作系统上的编译结果如下。
根据所生成的汇编程序来解释程序中四个变量的作用域、牛存期和置初值方式等方面的区别。
staticlongaa二10;
shortbb=20;
func()
staticlongcc二30;
shortdd=40;
}
编译生成的汇编代码如下:
.file,zstatic.c〃
・version〃01・01〃
gcc2_compilcd.:
•data
•align4
•typeaa,©object
.sizeaa,4
aa:
.long10
•globlbb
•align2
•typebb,@object
•sizebb,2
bb:
•value20
.align4
•typecc.2,@object
•sizecc.2,4
cc.2:
•long30
.text
.align4
•globlfunc
•typefunc,©function
func:
pushl%ebp
movl%esp,%ebp
subl$4,%esp
movw$40,-2(%ebp)
・L1:
leave
ret
.Lfel:
•sizefunc,•Lfel-func
.ident〃GCC:
(GNU)egcs-2.91.6619990314/Linux(egcs-1.1.2release),z
40.C语言是一种类型语言,但它不是强类型语言,因为编译时的类型检查不能保证所接受的程序没有运行吋的类型错误。
例如,编译吋的类型检查--般不能保证运行时没有数组越界。
请你再举一个这样的例子说明C语言不是强类型语言。
41.下面程序在SUN工作站上运行时陷入死循环,试说明原因。
如果将第8行的long*p改成short*p,并且将第23行longk改成shortk后,loop屮的循环体执行一次便停止了。
试说明原因。
main()
{
addr();
loop();
long*p;
loopO
{longi,j;
j=0;for(i=0;ivl0;i++){
(*p)・・;
j++;
}
addr()
{
longk;
k=0;
p二&k;
}
42.下面程序的结果是120o但是如果把第10行的abs(l)改成1的话,则程序结果是1,试分析为什么会有这不同的结果。
intfact()
{
staticinti=5;
if(i==0){
return(l);
}
else{
i=i-l;
return((i+abs(l))*fact());
main()printf(nfactorof5=%d\nl\fact());
}
43.一个C语言函数如下:
main()
{
inti,j,k;
i二5;
j=l;
while(j<100){
k=i+l;
j=j+k;
}
}
经优化编译后,生成的代码如下:
.file''optimize.c"
gcc2_compiled.:
gnu_compilcd_c:
・text
・align2
.globl_func
.type_func,©function
_func:
pushl%ebp
movl%esp,%ebp
movl$1,%eax
movl$6,%edx
・align2,0x90
L4:
addl%edx,%eax
cmpl$99,%eax
jleL4
leave
ret
Lfel:
・sizefunc,Lfel-func
试说明编译器对这个程序作了哪些种类的优化(只需要说复写传播、删除公共子表达式等,不需要说怎样完成这些优化的)。
44.对下面的流程图,假定各基本块出口之后的活跃变量均为a、b、f,循环中可用作固定的寄存器为RO、R1,则将RO、R1固定分配给循环中哪两个变量,可使执行代价节省得最多?
写出分析过程。
45.Pascal语言的repeat-unti.1语句的语法形式为
STrepeatSiuntilE
其语义解释为:
假
真
请按如下耍求构造该语句的翻译模式:
(1)写出适合语法制导翻译的产牛式;
(2)写出每个产生式对应的语义动作。