这是一篇持续增长的记录;
这是嵌套定义中 对非局部变量的引用,嵌套过程语言的栈式分配(c语言中不允许)我们所熟悉的PASCAL语言程序结构的特点是允许过程嵌套定义
question:主要特点:
(语言)一个过程可以引用包围它的任一外层过程所定义的标识符(如变量,数组或过程等)。
(实现)一个过程执行时可以引用它的任一外层过程的最新活动记录中的某些数据
(1) program sort(input, output); //sort的过程头
(2) var a: array [0..10] of integer;
(3) x: integer;
(4) procedure readarray; //sort内嵌套定义的readarray的过程头
(5) var i: integer;
(6) begin…a…end{readarray}; //readarray的过程体
(7) procedure exchange(i,j: integer); //sort内嵌套定义的exchange的过程头
(8) begin
(9) x∶=a[i]; a[i]∶=a[j]; a[j]∶=x; //exchange的过程体
(10) end{exchange};
(11) procedure quicksort(m,n: integer); //sort内嵌套定义的quicksort的过程头
(12) var k,v: integer;
(13) function partition(y,z:integer):integer;
//quicksort内嵌套定义的partition的函数头
(14) var i.j:integer;
(15) begin //partition的函数体
(16) …a…
(17) …v…
(18) exchange(i,j);
(19) end{partition};
(20) begin…end{quicksort}; //quicksort的过程体
(21) begin…end{sort} //sort的例程体
为了解决对非局部量的存取问题,必须设法跟踪每个外层过程的最新活动记录的位置。下面提供了两种方法。
1>用静态链解决对非局部量的引用(存取)
如果该程序的某次执行顺序为(调用次序): sort→quicksort→quicksort→partition→exchange…
用Display表解决对非局部量的引用(存取)
详细见编译原理第十章,运行的时候运行栈
。。。
。。。
。。
。。。
。。
编译的时候静态区,常量区,栈区。把变量分配到指定的位置。形成二进制流文件后,里面全是二进制代码, 这时代码区,数据区(常量放在DS中的PS中(这是一种方法)),堆栈区。先从代码区(CS)执行指令,堆栈段里过程记录表动态活动(这里就有函数栈的动态增长,(为什么说 返回局部指针是危险的 就表现在这里)函数调用完后SP返回到调用点的下一个位置,这时函数的局部指针所属的空间并不属于该函数,这里就出了非法访问的问题)若 访问数据区.........
。。。
。。。
。。。
。。
c语言中提供了 对活动记录表的操作的函数(具体见c语言经典三部书中)
#include <stdio.h> #include <string.h> #include <setjmp.h> jmp_buf begin;
//VC提供了在调试窗口运行的语句,值得一试 void print(char *p) { printf("%s\n",p); return ; } int main() { char buff[20];//这里的buff并不能放在setjmp的下面,这是由于c语言所限制,这样的话,buff将会保存上一次的值;如果我们 交换顺序,并把文件改成cpp,虽然可以运行,但是第二次并不会重新定义buff,;;这个强大的jmp用在默认恢复到未出错之前的状态,又是c语言的一大特色 。这远远不同于goto. if(setjmp(begin)){ printf("jmp sucessed\n"); } gets(buff); if(strcmp(buff,"restart") == 0) { longjmp(begin,3); } return 0; }