编译原理测验题Word格式文档下载.docx
《编译原理测验题Word格式文档下载.docx》由会员分享,可在线阅读,更多相关《编译原理测验题Word格式文档下载.docx(39页珍藏版)》请在冰豆网上搜索。
你可以按第215页图7.17的方式或者第219页图7.19的方式写出你的设计,不需要写产生中间代码的语法制导定义。
6.(5分)一个C语言程序如下:
func(i1,i2,i3)
longi1,i2,i3;
{
longj1,j2,j3;
printf("
Addressesofi1,i2,i3=%o,%o,%o\n"
&
i1,&
i2,&
i3);
Addressesofj1,j2,j3=%o,%o,%o\n"
j1,&
j2,&
j3);
}
main()
longi1,i2,i3;
func(i1,i2,i3);
该程序在某种机器的Linux上的运行结果如下:
Addressesofi1,i2,i3=27777775460,27777775464,27777775470
Addressesofj1,j2,j3=27777775444,27777775440,27777775434
从上面的结果可以看出,func函数的3个形式参数的地址依次升高,而3个局部变量的地址依次降低。
试说明为什么会有这个区别。
7.(15分)一个C语言程序及其在某种机器linux操作系统上的编译结果如下。
根据所生成的汇编程序来解释程序中四个变量的作用域、生存期和置初值方式等方面的区别。
staticlongaa=10;
shortbb=20;
func()
staticlongcc=30;
shortdd=40;
.file"
static.c"
.version"
01.01"
gcc2_compiled.:
.data
.align4
.typeaa,@object
.sizeaa,4
aa:
.long10
.globlbb
.align2
.typebb,@object
.sizebb,2
bb:
.value20
.typecc.2,@object
.sizecc.2,4
cc.2:
.long30
.text
.globlfunc
.typefunc,@function
func:
pushl%ebp
movl%esp,%ebp
subl$4,%esp
movw$40,-2(%ebp)
.L1:
leave
ret
.Lfe1:
.sizefunc,.Lfe1-func
.ident"
GCC:
(GNU)egcs-2.91.6619990314/Linux(egcs-1.1.2release)"
8.(10分)C语言是一种类型语言,但它不是强类型语言,因为编译时的类型检查不能保证所接受的程序没有运行时的类型错误。
例如,编译时的类型检查一般不能保证运行时没有数组越界。
请你再举一个这样的例子说明C语言不是强类型语言。
9.(10分)如果在A机器上我们有C语言编译器CCA,也有它的源码SA(用C语言写成)。
如何利用它通过尽量少的工作来得到B机器的C语言编译器CCB。
10.(5分)表达式(x.(yz.(x+y)+z)3)45和(x.(yz.(x+y)+z)35)4有同样的结果。
在抽象机FAM上,哪一个表达式对应的目标代码的执行效率高?
为什么?
2001年编译原理试题参考答案
1.
2.LR
(1)文法LR
(1)文法二义文法
SAB|aABbSABSAASb|
AaaAb|AaaAb|ab|Aa|
BBb|BBb|
3.intrealid,$
DDTLDTL
TTintTreal
LLidR
RR,idRR
4.SSprint(S.num)
S(L)S.num:
=L.num+1
SaS.num:
=0
LL1,SL.num:
=L1.num+S.num
LSL.num:
=S.num
S{S.depth:
=0}S
S{L.depth:
=S.depth+1}(L)
Sa{print(S.depth)}
L{L1.depth:
=L.depth}L1,{S.depth:
=L.depth}S
L{S.depth:
5.t1:
=initial
t2:
=final
ift1>
t2gotoL1
v:
=t1
L2:
stmt
ifv=t2gotoL1
=v+1
gotoL2
L1:
6.由于实参表达式是反序进入活动记录,而局部变量是顺序在活动记录中分配。
7.aa是静态外部变量,而bb是外部变量,它们都分配在静态数据区(由.data伪指令开始),但是bb由伪指令.globl指明为全局的,用来解决其它文件中对bb的外部引用,而aa只能由本文件引用。
cc是静态局部变量,同aa和bb一样,它的生存期是整个程序并分配在静态数据区。
由于cc在源程序中的作用域是函数func的体,而在目标文件中,它的作用域至少已是整个文件了,为避免同源文件中外部变量和其它函数的静态局部变量的名字冲突,所以要对它进行改名,成了cc.2。
由于cc不是全局的,因此cc.2前面没有伪指令.globl。
dd是自动变量,其作用域是函数func的体,其生存期是该函数激活期间,因此它分配在栈区,并且置初值是用运行时的赋值来实现。
8.例如联合体的类型检查一般也不可能在编译时完成,虽然下面例子是可静态判断类型错误的。
unionU{intu1;
int*u2;
}u;
intp;
u.u1=10;
p=u.u2;
p=0;
9.修改源码SA的代码生成部分,让它产生B机器的代码,称结果程序为SB。
将SB提交给CCA进行编译,得到一个可执行程序。
将SB提交给上述可执行程序进行编译,得到所需的编译器CCB。
10.第一个表达式在执行yz.(x+y)+z)3时出现参数个数不足的情况,因此有FUNVAL的值进入栈顶,然后发现参数个数不足,又把它做成FANVAL的情况。
而第二个表达式执行的是(yz.(x+y)+z)35,不会出现参数个数不足的情况。
因此第二个表达式的执行效率比第一个表达式的高。
2003年编译原理试题
1.(20分)写出字母表={a,b}上语言L={w|w中a的个数是偶数}的正规式,并画出接受该语言的最简DFA。
2.(15分)考虑下面的表达式文法,它包括数组访问、加和赋值:
EE[E]|E+E|E=E|(E)|id
该文法是二义的。
请写一个接受同样语言的LR
(1)文法,其优先级从高到低依次是数组访问、加和赋值,并且加运算是左结合,赋值是右结合。
3.(10分)下面是产生字母表={0,1,2}上数字串的一个文法:
SDSD|2
D0|1
写一个语法制导定义,它打印一个句子是否为回文数(一个数字串,从左向右读和从右向左读都一样时,称它为回文数)。
4.(10分)教材上7.2.1节的翻译方案
P{offset:
=0}
D
DD;
D
Did:
T{enter(id.name,T.type,offset);
offset:
=offset+T.width}
Tinteger{T.type:
=integer;
T.width:
=4}
Treal{T.type:
=real;
=8}
使用了变量offset。
请重写该翻译方案,它完成同样的事情,但只使用文法符号的属性,而不使用变量。
5.(5分)一个C语言程序如下:
voidfun(struct{intx;
doubler;
}val){
main()
{
struct{intx;
}val;
fun(val);
}
该程序在X86/Linux机器上的用cc命令编译时,报告的错误信息如下:
1:
warning:
structuredefinedinsideparms
anonymousstructdeclaredinsideparameterlist
itsscopeisonlythisdefinitionordeclaration,
whichisprobablynotwhatyouwant.
7:
incompatibletypeforargument1of‘fun’
请问,报告最后一行的错误的原因是什么?
如何修改程序,使得编译时不再出现这个错误信息。
6.(10分)一个C语言程序如下:
typedefstruct_a{
shorti;
shortj;
shortk;
}a;
typedefstruct_b{
longi;
}b;
printf("
Sizeofshort,long,aandb=%d,%d,%d,%d\n"
sizeof(short),sizeof(long),sizeof(a),sizeof(b));
该程序在X86/Linux机器上的运行结果如下:
Sizeofshort,long,aandb=2,4,6,8
已知short类型和long类型分别对齐到2的倍数和4的倍数。
试问,为什么类型b的size会等于8?
7.(15分)一个C语言程序如下:
intfact(i)
inti;
if(i==0)
return1;
else
returni*fact(i