编译原理第二次习题课 王静.

Slides:



Advertisements
Similar presentations
第 8 章 数组 计算机科学学院 李淮 Tel QQ
Advertisements

探究实验的教学设计和教学策略 ENTER 余杭勾庄中学 郭 琳
基本概論 Basic concepts.
电子成绩单项目实现.
编 译 原 理 指导教师:杨建国 二零一零年三月.
性理釋疑(1—30題) 後學 阮章輝 學講.
Loops.
第一章 C语言概述 计算机公共教学部.
程序设计基础知识.
广东省现代农业产业体系柑橘遗传育种创新团队 广东省农科院果树研究所 周碧容
贴近教学 服务师生 方便老师.
第六章 中间代码生成 赵建华 南京大学计算机系.
資料結構與C++程式設計進階 資料結構概論 講師:林業峻 CSIE, NTU 6/ 7, 2010.
苏教版小学数学六年级(下册) 认识正比例的量 执教者:朱勤.
第9章 运行时的存储组织 重点:符号表的内容、组织,过程调用实现, 难点:参数传递,过程说明语句代码结构,
编译原理与技术 中间代码生成 2018/9/17 《编译原理与技术》讲义.
7 Intermediate Representation
C语言程序设计 第十二章 位运算.
编译原理与技术 第7章 中间代码生成 3学时.
补充内容 结构体 概述 定义结构体类型和定义结构体变量 结构体变量的引用 结构体变量的初始化 指针与结构体 用typedef定义类型的别名.
编译原理与技术 类型检查 2018/11/21 《编译原理与技术》-类型检查.
If … else 選擇結構 P27.
结构体和共用体 2 梁春燕 华电信息管理教研室.
第六章 运行时存储空间的组织和管理 术语 本章内容 讨论一个活动记录中的数据布局 程序执行过程中,所有活动记录的组织方式 过程的活动
授课老师:龚涛 信息科学与技术学院 2018年3月 教材: 《Visual C++程序员成长攻略》 《C++ Builder程序员成长攻略》
第三章 词法分析.
摩擦力.
作弊是否很有诱惑性? 上堂课已经讲了 作业不一定在两个小时里都能完成 答疑没有一个人? 作弊是有记录的 心理系很多同学集体作弊,让人震惊
7.4 布尔表达式和控制流语句 布尔表达式有两个基本目的 计算逻辑值 c = (a > b) && a > 1
明解C++教學手冊 柴田望洋 博士 著 書號:PG20269
中间代码生成.
第三节 整数类型.
2.1 C语言的数据类型 2.2 常量与变量 2.3 变量赋初值 2.4 各类数值型数据间的混合运算 2.5 C语言的运算符和表达式
小太陽兒童人文藝術學院兒童畫展 地點:住院大樓9F、11F外走道( )
Struct結構 迴圈
第1章 概述 本章要点: C语言程序结构和特点 C语言程序的基本符号与关键字 C语言程序的编辑及运行 学习方法建议:
C语言程序设计.
第十章 用户自定义数据类型 目录 学生信息管理系统的开发 结构体数据类型的概述 结构体变量的使用 结构体数组
目录 9.1 结构体类型 9.2 共用体类型 9.3 枚举类型 9.4 类型声明符typedef 1.
C语言概述 第一章.
第1讲 C语言基础 要求: (1) C程序的组成 (2) C语言的标识符是如何定义的。 (3) C语言有哪些基本数据类型?各种基本数
第四节 浮点数类型.
中華大學 資訊工程學系 報告人:資訊工程學系 許慶賢 系主任.
Java變數 2014/6/24.
4 條件選擇 4.1 程式基本結構 循序式結構 選擇式結構 重複式結構 4-3
第六章 语法制导的翻译 本章内容 介绍一种语义描述方法:语法制导的翻译,介绍语法制导的翻译的实现方法。
第 二 章 数据类型、运算符与表达式.
團體衛生教育護理創意競賽 報告者:護理科 計畫主持人邱馨誼講師
第11章 位运算 为了节省内存空间,在系统软件中常将多个标志状态简单地组合在一起,存储到一个字节(或字)中。C语言是为研制系统软件而设计的,所以她提供了实现将标志状态从标志字节中分离出来的位运算功能。 所谓位运算是指,按二进制位进行的运算。 11.1 数值在计算机中的表示 11.2.
习题课
指標
C++语言程序设计教程 第2章 数据类型与表达式 第2章 数据类型与表达式 制作人:杨进才 沈显君.
习题课 编译原理与技术 计算机科学与技术学院 李诚.
<编程达人入门课程> 本节内容 为什么要使用变量? 视频提供:昆山爱达人信息技术有限公司 官网地址: 联系QQ:
第3章 数据类型、运算符与表达式.
第7章 程序的结构 四、生存期与存储属性 五、extern关键字与外部连接属性 六、static关键字与内部连接属性.
第二章 类型、对象、运算符和表达式.
陣列 東海大學物理系‧資訊教育 施奇廷.
C/C++基礎程式設計班 C++: 物件的使用、參考、重載函式 講師:林業峻 CSIE, NTU 3/28, 2015.
本节内容 指针数组与数组指针 视频提供:昆山爱达人信息技术有限公司 官网地址: 联系QQ: QQ交流群 : 联系电话:
第八节 算术运算符和算术表达式.
#include <iostream.h>
第3章 最简单的C程序设计 3.1 顺序程序设计举例 3.2 数据的表现形式及其运算 3.3 C语句 3.4 数据的输入输出.
本节内容 指针类型.
第十二章 位运算.
4. 曾文水庫越域引水環評報告彙整 資料來源: 1. 曾文水庫越域引水下游輸水工程環境影響差異分析暨環境現況差異分析及對策檢討報告(定稿本)
C/C++基礎程式設計班 C語言入門、變數、基本處理與輸入輸出 講師:林業峻 CSIE, NTU 3/7, 2015.
變數與資料型態  綠園.
第三章 流程控制 程序的运行流程 选择结构语句 循环结构语句 主讲:李祥 时间:2015年10月.
本节内容 指针类型 视频提供:昆山爱达人信息技术有限公司 官网地址: 联系QQ: QQ交流群 : 联系电话:
Presentation transcript:

编译原理第二次习题课 王静

(a) array(0..99, pointer(real)) (b) array(0..9, array(0..19, integer) 5.4 为下列类型写类型表达式 (a)指向实数的指针数组,数组的下标从0到99 (b)两维数组,它的行下表从0到9,列下标从0到19. (c)函数,它的定义域是从整数到整数指针的函数,它的值域是 由一个整数和一个字符组成的纪录。 (a) array(0..99, pointer(real)) (b) array(0..9, array(0..19, integer) (c) 假定作为值域的记录类型的两个值域分别叫做i和c, 那么该函数的类型表达式为 (integer  pointer(integer))  record((i*integer)*(c*char)

5. 6 下列文法定义字面常量表的表。符号的解释和图5 5.6 下列文法定义字面常量表的表。符号的解释和图5.2文法的那些相同,增加 了类型list, 它表示类型T的元素表。 P  D; E | T  list of T | char | integer D  D; D | id : T | E  (L) | literal | num | id | L  E, L | E 写一个类似5.3节中的翻译方案,以确定表达式(E)和表(L)的类型 P  D; E D  D; D D  id : T { addtype(id.entry, T.type) } //addtype函数将id的 T  char { T.type := char } //类型添到符号表中 T  integer { T.type := integer } T  list of T1 { T.type := list (T1.type) } E  literal { E.type := char } E  num { E.type := integer } E  id { E.type := lookup(id.entry) } // 取符号表中id指向的条目 E  (L) { E.type := list (L.type) } //的类型 L  E { L.type := E.type } L E | L1 { L.type := (L1.type = E.type)? L1.type : E.type

(a) ref :∀α.α  pointer(α) (b) arrayderef: 5.14 使用类型变量表示下列函数的类型 (a)函数ref,它取任意类型的对象作为变元,返回这个对象的指针 (b)函数arrayderef,它以一个数组为变元,数组的下标是整型,数组 的元素是某类型的指针,返回一个数组,它的元素是变元数组的元素 所指向的对象。 (a) ref :∀α.α  pointer(α) (b) arrayderef: ∀α.array(integer,pointer(α) array(integer,α)

6.3 考虑下面的c语言程序: (a)该程序经先前某些C编译器的编译,其目标程序的运行结果是: cp1 = abcdefghij cp2 = ghij 试分析,为什么cp2所指的串被修改了 (b)在x86/Linux机器上经gcc编译后,该程序运行报告段错误,请分析原因。 main() { char * cp1,* cp2; cp1 = "12345"; cp2 = "abcdefghij"; strcpy(cp1,cp2); printf("cp1 = %s \n cp2 = %s \n", cp1,cp2); } (a) 1 2 3 4 5 \ 0 a b c d e f g h i j \ 0 ↑ cp1 ↑ cp2 执行了串拷贝操作后,上面变为 a b c d e f g h i j \0 f g h i j \0 ↑ cp1 ↑ cp2 而cp2的地址没有改变,所以cp2所指的串被修改了 (b)编译器把程序中的字符串常量分配在一个段中,该 段内容在运行中不能被修gi啊。

6. 4 typedef struct _a{ typedef struct _b{. char c1;. char c1; 6.4 typedef struct _a{ typedef struct _b{ char c1; char c1; long i; char c2; char c2 ; long i; double f; }a; double f; }b; 该程序在SPARC/Solaris工作站上的运行结果:Size of a,b = 24, 16 在x86/Linux机器上运行时,结果是: Size of a,b = 20,16 结构体类型a和b的域都一样,仅次序不同,为什么他们需要的存储空间不一样? 这是由于数据的对齐问题的影响。 SPARC/Solaris上以8对齐 对于a : (1 + 4)取 8 +(1)取8 + 8 = 24 对于b : (1+1+4) 取 8 + 8 = 16 x86/Linux 上以4对齐 对于a : (1)取4 + 4 +(1)取4 + 8 = 20 对于b: (1+1)取4 + 4 + 8 = 16

f1的声明不做类型检查,f2的声明会做类型检查 6.12下面是一个C语言程序: long f1(i) long I;{ return (i*10); } long f2(long i){ return (i*10); } main() { printf(“f1=%d,f2=%d\n”, f1(10.0), f2(10.0)); 其中函数f1和f2仅形式参数的描述方式不一样。该程序在x86/Linux机器上的运行结果为:f1=0,f2=100.请解释原因 f1的声明不做类型检查,f2的声明会做类型检查 在编译函数调用f1(10.0)时,会把浮点数10.0转换 成双精度型,并将其压栈,其低地址的4个字节看成 整数时正好时0. 在编译函数调用f2(10.0)时,会把浮点数10.0转换 成整数10,并将其压栈,于是结果是100.

a :array(2,array(4,char)) p :array(2, pointer(char)) 6.14 一个C文件array.c仅有下面两行代码: char a[][4] = {“123”, “456”}; char *p[] = {“123”, “456”} 写出数组a和指针p的类型表达式 a :array(2,array(4,char)) p :array(2, pointer(char))

main(){ long I; (a)sizeof(a) = 0 * 4 = 0; (b)a[0][0]指向的实际还是i; 6.18 下面是一个C语言程序 虽然出现long a[0][4]这样的声明,在x86/Linux机器上的该程序还是能通过编译并生产目标代码。请回答下面两个问题: (a) sizeof(a)的值是多少? (b) a[0][0]的值是多少? main(){ long I; long a[0][4]; long j; I = 4; j = 8; printf(“%d,%d\n”, sizeof(a), a[0][0]);} (a)sizeof(a) = 0 * 4 = 0; (b)a[0][0]指向的实际还是i;

参数是逆序计算进栈的,因此 先调用f(f),此时,n变为0, 因此再打印n的时候,打印的 结果为0. 6.23 一个C语言程序如下 该程序的运行结果不是所期望的 5 factorial is 120 而是 0 factorial is 120 试说明原因。 int n; Int f(g) int g();{ int m; m = n; if (m == n) return 1; else { n = n -1; return m*g(g); }} main(){ n = 5; printf(“%d factorial is %d\n”, n, f(f));} 参数是逆序计算进栈的,因此 先调用f(f),此时,n变为0, 因此再打印n的时候,打印的 结果为0.

7.4 修改图7.5中计算声明的类型和相对地址的翻译方案,允许名字 表而不是单个名字出现在形式为D->id: T的声明中 D → L:T { L.type = T.type ; L.width = T.width } L→ id,L 1 { enter ( id.name , L.type , offset ) ; offset = offset + L.width ; L1.type = L.type ; L1.width = L.width } L→id { enter ( id.name , L.type , offset ) ; offset = offset + L.width }

需要修改 E→ E1 or E2 和 E→ id1 relop id2 两个产生式的 语法 制导定义。 7.8 表7.3的语法制导定义把B-> E1< E2翻译成一对语句 if E1.place< E2.place goto … goto ... 可以用一个语句 if E1.place>= E2.place goto... 来代替,当B是真时执行后继代码。修改表7.3的语法制导定义,使之产生这种性质的代码。 需要修改 E→ E1 or E2 和 E→ id1 relop id2 两个产生式的 语法 制导定义。 E→ E1 or E2 E1.true = E.true ; E1.false = newlable ; E2.true = E.true ; E2.false = E.false ; E.code = E1.code || gen ( ‘goto’ E1.true ) || gen (E1.false ‘:’ ) || E2.code E→ id1 relop id2 E.code = gen ( ‘if’ id1.place conreop id2.place ‘goto’E.false) conrelop 为原 relop 关系运算符的‘非’关系运算符。

(a)编译器每次遇到可能会跳转到此处的地方会预 7.10 题目略 (a)编译器每次遇到可能会跳转到此处的地方会预 留一个标记,当后面的代码需要跳转时又会在相应 的 地方添加标记,所以会有多条。 (b) L1 是预留给返回的, 本函数没有return,所以 没用L1