2013.12.8 7.4 修改图 7.5 中计算声明名字的类型和相对地址的翻译方案, 允许名字表而不是单个名字出现在形式为 D id : T 的声明中 即允许 a, b, c : integer 这种形式的变量声明 2013.12.1 6.12 下面是一个 C 语言程序 : long f1( i ) long i; { return(i 10); long f2(long i) { return(i 10); printf( f1 = %d, f2 = %d\n, f1(10.0), f2(10.0) ); 其中函数 f1 和 f2 仅形式参数的描述方式不一样 该程序在 x86/linux 机器上的运行结果如下 : f1 = 0, f2 = 100 请解释为什么用同样的实在参数调用这两个函数的结果不一样 6.14 一个 C 文件 array.c 仅有下面两行代码 : char a[ ][4] = { 123, 456 ; char p[ ] = { 123, 456 ; 从编译生成的下列汇编代码可以看出对数组 a 和指针 p 的存储分配是不同的 试依据这里的存储分配, 为置 了初值后的数组 a 和指针 p 写出类型表达式.file array.c.globl a.data.type a, @object.size a, 8 a:.string 123.string 456.section.rodata.LC0:.string 123.LC1:.string 456.globl p.data.align 4.type p, @object.size p, 8 p:.long.lc0.long.lc1.section.note.gnu-stack,, @progbits.ident GCC: (GNU) 3.3.5 (Debian 1:3.3.5-13) 6.16 一个 C 语言的函数
func(c,l) char c;long l; { func(c,l); 在 x86/linux 机器上编译生成的汇编代码如下 :.file "parameter.c".version "01.01" gcc2_compiled.:.text.align 4.globl func.type func,@function func: pushl %ebp // 将老的基地址指针压栈 movl %esp,%ebp // 将当前栈顶指针作为基地址指针 subl $4,%esp // 分配空间 movl 8(%ebp),%eax movb %al,-1(%ebp) movl 12(%ebp),%eax pushl %eax movsbl -1(%ebp),%eax pushl %eax call func addl $8,%esp.L1: leave // 和下一条指令一起完成恢复老的基地址指针, 将栈顶 ret // 指针恢复到调用前参数压栈后的位置, 并返回调用者.Lfe1:.size func,.lfe1-func.ident "GCC: (GNU) egcs-2.91.66 19990314/Linux (egcs-1.1.2 release)" 请说明字符型参数和长整型参数在参数传递和存储分配方面有什么区别 ( 小于长整型 size 的整型参数的处理方式和字符型参数的处理方式是一样的 ) 2013.11.23 6.2 一个 C 程序的三个文件 head.h file1.c 和 file2.c 的内容分别如下 : head.h: file1.c: file2.c: short int a = 10; #include "head.h" #include "head.h" 在 X86/Linux 机器上的编译命令如下 : cc file1.c file2.c 编译结果报错的主要信息如下 : multiple definition of a 试分析为什么会报这样的错误
6.3 考虑下面的 C 语言程序 : char cp1, cp2; cp1 = "12345"; cp2 = "abcdefghij"; strcpy(cp1,cp2); printf("cp1 = %s\ncp2 = %s\n", cp1, cp2); (a) 该程序经先前某些 C 编译器的编译, 其目标程序的运行结果是 : cp1 = abcdefghij cp2 = ghij 试分析, 为什么 cp2 所指的串被修改了? (b) 在 x86/linux 机器上经 gcc 编译器编译后, 该程序运行时, 操作系统报告段错误 (segmentation error) 并终止运行, 请分析原因 6.6 下面是 C 语言两个函数 f 和 g 的概略 ( 它们不再有其它的局部变量 ): int f (int x) { int i; return i +1; int g (int y) {int j; f (j +1); 请按照图 6.11 的形式, 画出函数 g 调用 f,f 的函数体正在执行时, 活动记录栈的内容及相关信息, 并按图 6.10 左侧箭头方式画出控制链 假定函数返回值是通过寄存器传递的 2013.11.16 5.9 修改 5.3.3 节的翻译方案, 使之能处理 : (a) 各种有值语句 赋值语句的值是赋值号右边的表达式的值, 条件语句或循环语句的值是语句体的值, 语句表的值是表中最后一个语句的值 (b) 布尔表达式 加上逻辑算符 and, or 及 not 和关系算符的产生式 然后给出适当的翻译规则, 它们检 查这些表达式的类型 5.13 在文件 stdlib.h 中, 关于 qsort 的外部声明如下 : extern void qsort(void, size_t, size_t, int ( )(const void, const void )); 下面 C 程序所在的文件名是 type.c, 用某个 C 编译器编译时, 错误信息如下 : type.c:18: warning: passing argument 4 of qsort from incompatible pointer type 请对该程序略作修改, 使得该警告错误能消失, 并且不改变程序的结果 注 : 程序中关于变量 asthypo 和 n 的赋值以及其他部分被略去 #include <stdlib.h> typedef struct{ int Ave; double Prob; HYPO; HYPO *asthypo; int n; int HypoCompare(HYPO *sthypo1, HYPO *sthypo2) { if (sthypo1->prob>sthypo2->prob){ return(-1); else if (sthypo1->prob<sthypo2->prob) {
return(1); else{ return(0); /* end of function HypoCompare */ qsort ( asthypo,n,sizeof(hypo),hypocompare); 2013.11.9 4.10 文法如下 : S ( L ) a L L, S S (a) 写一个翻译方案, 它输出每个 a 的嵌套深度 例如, 对于句子 ( a, ( a, a) ), 输出的结果是 1 2 2 (b) 写一个翻译方案, 它打印出每个 a 在句子中是第几个字符 例如, 当句子是 ( a, ( a, ( a, a ), (a) ) ) 时, 打印的结果是 2 5 8 10 14 4.13 下面是构造语法树的一个 S 属性定义 将这里的语义规则翻译成 LR 翻译器的栈操作代码段 E E1 + T E.nptr = mknode ('+', E1.nptr, T.nptr) E E1 T E.nptr = mknode (' ', E1.nptr, T.nptr) E T E.nptr = T. nptr T ( E ) T.nptr = E. nptr T id T.nptr = mkleaf ( id, id.entry) T num T.nptr = mkleaf ( num, num.val) 2013.11.2 4.5 给出对表达式求导数的语法制导定义, 表达式由 + 和 * 作用于变量 x 和常数组成, 如 x*(3*x + x*x), 并假定没有任何化简, 例如将 3*x 翻译成 3*1+0*x 2013.10.26 3.21 证明下面文法 S Aa bac dc bda A d 是 LALR(1) 文法, 但不是 SLR(1) 文法 3.31 为语言 L = { w w (a b)* 并且在 w 的任何前缀中,a 的个数不少于 b 的个数 写三个文法, 它们分别是 LR(1) 的 二义的和非二义且非 LR(1) 的 2013.10.19 3.18. 考虑下面的文法 E E + T T T T F F F F* a b (a) 为此文法构造 SLR 分析表 (b) 构造 LALR 分析表
3.20 (a) 证明下面文法 S AaAb BbBa A ε B ε 是 LL(1) 文法, 但不是 SLR(1) 文法 2013.10.5 3.10 构造下面文法的 LL(1) 分析表 D TL T int real L id R R, id R ε 3.11 下面的文法是否为 LL(1) 文法? 说明理由 S A B P Q x A x y B b c P d P ε Q a Q ε 2013.9.21 2.11 可以从正规式的最简 DFA 同构来证明两个正规式等价 使用这种技术, 证明正规式 (a b) (a b ) 和 ( (ε a )b ) 等价 3.4 文法 R R ' ' R R R R ( R ) a b 产生字母表 {a, b 上所有不含 ε 的正规式 注意, 第一条竖线加了引号, 它是正规式的或运算符号, 而不是文 法产生式右部各选择之间的分隔符, 另外星号 在这儿是一个普通的终结符 该文法是二义的 (a) 证明该文法产生字母表 {a, b 上的所有正规式 (b) 为该文法写一个等价的非二义文法 它给予算符 连接和 的优先级和结合性同 2.2 节中定义的一致 (c) 按上面两个文法构造句子 ab b a 的分析树 2013.9.14 2.4 为下列语言写正规定义 (e) 最多只有一处相邻数字相同的所有数字串