维普资讯 http://www.cqvip.com
第l6卷第3期 长春大学学报 V01.16 No.3 2006年6月 JOURNAL OF CHANGCHUN UNIVERSⅡY June 2O06 文章编号:1009—3907(2006)o3—0042—03 浅析pl/O与C编译程序在子过程处理上的异同 宋雅娟,刘 刚 邱敏瑞 (长春大学计算机科学技术学院,吉林长春130022) 摘要:讨论了pl/0语言与c语言程序在处理子过程问题上的区别,并阐述了二者的编译程序为 保证语言的子过程使用规则,在编译方面处理上的异同点,主要区别是是否需要存取链来保证是否 支持子过程的嵌套定义,pl/0需要使用存取链,而c语言不需要,因为c语言不支持函数的嵌套定 义而PL/o语言支持。 关键词:存取链;子过程处理;编译程序 中图分类号:TP314 文献标识码:A pl/0是pascal语言的一个子集,在子过程的处理上与pascal语言一致。而现在计算机专业所讲授的编 程语言一般都是c语言,它在子过程的处理上与pascal区别较大。笔者针对教学过程,在本文中对c语言 与pl/0语言的子过程进行了区别,并对二种语言的编译程序在子过程处理上的异同进行了详细阐述。 1 pl/0语言与C语言在使用子过程上的异同 pl/0语言与c语言均是面向过程的计算机高级语言,它们都支持程序的 模块化设计,可以将程序分割成多个子过程,通过各个子过程的彼此调用来 完成整个程序功能,但是在子过程的定义上这两种语言存在着极大的不同。 1.1 pl/O语言支持子过程的嵌套定义和受限的过程调用 pl/0语言可在一个过程内部定义子过程,这称为子过程的嵌套定义,定 义子过程的过程可称为父过程。如图l所示的子过程嵌套定义示意图,在该 图中P10为主过程,Prol和Pro2是在pl0中定义的子过程,Pro3和Pro4是在 子过程Pro2中定义的嵌套子过程,在pl/0子过程的调用规则是这样的: (1)过程可调用自己直接定义的子过程,如pl0可直接调用Prol和Pro2, 而Pro2可直接调用Pro3和Pro4。 (2)同级子过程,后定义的子过程可调用在其前定义的子过程,反之不 行。如Pr0l和Pm2同是在主过程中声明的子过程,它们为同级子过程,但Pro2 定义在Prol后面,则Pro2可调用Pro1。 图 pl/O语言中子过程 (3)在子过程内不仅可以定义嵌套的子过程,还可定义自己的常量和变量,在PI/O中,一个子过程内声 明的所有的数据均可由其本身及其所有子孙过程引用,反之不行。 (4)因为所有的子过程的定义均在主过程内部,所以主过程中的数据可由自身及其所有子孙过程访问。 即所有的子过程均可访问,所以在主过程中定义的变量可作为全局变量使用。 1.2 C语言支持子过程的自由调用但不支持子过程的嵌套定义 在c语言中,将所有的子过程称为函数,以下均用函数称谓子过程。 (1)C语言不支持函数的嵌套定义。 收稿日期:2005-10・10 作者简介:宋雅娟(1974一),女,吉林省柳河县人,长春大学计算机科学技术学院讲师,博士生,主要从事计算机软件理论研究。 维普资讯 http://www.cqvip.com
第3期 宋雅娟,等:浅析pl/O与c编译程序在子过程处理上的异同 43 (2)每个函数中定义的数据均只能由该函数自己使用,称为局部变量。 (3)在C语言程序中必须有一个主函数main(),但该函数只是作为程序执行时的人口点,不具有任何其 他特殊地位,其中定义的变量也只是作为自己使用的局部变量,不能由任何函数使用。 (4)C语言中的函数调用比较自由,除main函数不能被调用外,其他函 数均可互相调用 ]。如图2所示,其中每个矩形表示一个子过程,箭头表示 调用关系。 由上述说明,可了解到pl/O或者pascal语言和C语言在处理子过程上 的区别,那么在对这两种语言的源程序进行编译时需要对子程序进行什么样 的处理才能满足上述不同的规则呢? 2 pL/O和c语言的编译程序在处理子过程上的异同 2 C语言中函数定义及调用示意图 笔者通过使用Microsoft Visual C++6.0的反汇编工具取得了对C语言源程序编译后的汇编程序,经过 与教材上的pl/O编译程序源代码进行反复比较,了解了这两种编译程序在处理子过程上的异同。 2.1 两种编译程序在子过程处理上的相同点 2.1.1数据区切换 在子过程运行过程中,各过程的数据区都是使用堆栈式数据结构来完成的,即满足后进先出的原则,最 后被调用的子过程先结束。假设发生的调用过程如下,即主过程调用Pro2,而Pro2调用Pro4,则首先在栈中 为主过程分配数据区,当发生Pro2过程调用时,在栈顶为Pro2开辟数据区,当在Pro2中调用Pro4时,在栈 顶继续为Pro4开辟数据区,如图3(a)所示。当Pro4执行结束,则释放其数据区,栈中状态如图3(b)所示, 如果Pm2又调用Pro3,则在栈顶为Pro3开辟数据区。如图3(C)所示。在程序执行过程中,过程调用是动态 进行的,堆栈区的数据也是在动态变化的,从图3中也可看出栈的基点总是随着过程调用发生变化的,总是 指向正在执行的子过程的数据基底,当子过程结束时,栈基要指回调用该过程的数据区基底。所以发生过程 调用时要保留主调过程的栈基,这样在被调过程结束时才能恢复主调过程的数据区基底,这不论是在pl/O 语言编译程序还是在C语言编译程序中都是一样的。 栈基 P r()4数据区 栈基 Pro4数据区 Pro2数据区 栈基 主过程 数据区 Pro2数据区 Pro2数据区 主过程 数据区 主过程 数据区 (a)Pro4被渊用(b)Pro4 ̄行结束 图3过程调用数据区变化不意图 (c)Pro3被调用 2.1.2代码切换 当发生过程调用时,需暂停主调过程的代码运行,而转去执行被调过程的代码,当被调过程代码执行结 束,需返回主调过程被暂停处继续执行,这就需要记录暂停点,即返回地址,这也是要保存在栈中的,这在两 种语言中均是相同的。 2.2两种编译程序在子过程处理上的不同 (1)pl/O编译程序中使用存取链来实现过程的嵌套定义。pl/O语言支持子过程的嵌套定义,由此而引 出对祖先过程定义的变量可直接使用。为此pl/O编译程序在处理子过程定义部分时,要特别记录每个过程 的父过程信息,从而可在以后使用其祖先过程的数据。当发生过程调用时,需要根据记录的父过程信息而在 堆栈中指向其父过程的数据基,在pl/O中称为存取链(或静态链)。以主过程调用Pro2,而Pro2调用Pml为 例,图4是PI/O在处理过程调用中使用存取链的图示。在图4中可看出,Pml和Pm2均为主过程定义的子 过程,Pml是由它的同级子过程调用,根据图4(a),Pml与其父过程之间隔着Pm2,而Pm2为Pml的主调过 维普资讯 http://www.cqvip.com
长春大学学报 第16卷 程。Prol可存取其父过程即主过程定义的变量,但不能 存取其同级子过程Pro2的变量,因此在Prol中堆栈区中 Pro3数据区 设一个存取链指向其父过程P10,而Pro2的存取链也指向 栈基 存取链一 P10,这样Prol和Pro2不仅可以存取自己的变量,还可以 Pro2数据区 存取顺存取链所能找到的数据区的变量。如果用图3 存取链 (C)所示的过程调用关系来表示pi/0的父子关系,则如 P10数据区 图4(b)所示,这样Pro3可顺存取链访问其父过程Pro2 (a)同级过程存取链 (b)嵌套过程存取链 的变量,又可顺Pro2的静态链访问主过程的变量。 (2)C语言编译程序不支持存取链特征。C语言的 图4 pl/O编译程序中存取链示意图 函数不支持嵌套定义,不存在父子函数的问题,也不存在一个函数访问另一个函数所定义的变量问题,所以 在编译过程中不使用存取链。 3结语 C语言和PL/O在子过程的定义规则和调用规则上区别较大,pL/O支持子过程的嵌套定义,在调用规则 上比较严谨,只能由父过程调用直接嵌套定义的子过程,或者由后定义的子过程调用先定义的同级子过程; 在变量的使用上区别也非常大。而C语言不支持函数即子过程的嵌套定义,在调用上除主函数main()不能 被其他函数调用外,其他调用不受,而且每个函数内定义的变量只能由自己使用,称为局部变量,main 函数也不例外。这就导致了两种语言的编译程序在实现上的差别,pl/O语言编译程序在子过程调用时要保 存能够使其访问祖先过程变量的存取链信息,这是C语言编译器及其他不支持子过程嵌套定义的高级语言 编译程序所不具有的。 参考文献: [1] 吕映芝,张素琴,蒋维杜.编译原理[M].北京:清华大学出版社,1998. [2] 谭浩强.c程序设计[M].北京:清华大学出版社,2000. [3]金成植.编译程序构造原理和实现技术[M].北京:高等教育出版社,2000. [4]刘磊.编译原理及实现技术[M].北京:机械工业出版社,2005. [5]Alfred V.Aho.Ravi Sethi.Jeffre D.Ullman.Compilers:Principles,Techniques,and Tools[M].北京:人民邮电出版社,2001. 责任编辑:钟声 A brief analysis of similarities and diferences of pl/O and C language compiler in sub-procedure SONG Ya—juan,LIU Gang,QIU Min-rui (Computer Science and Techonology Institute,Changchun University,Changchun 1 30022,China) Abstract:This thesis discusses the diferences on treeing sub・procedure between pL/O languange and C language and expatiates their compilers’similarities and differences on sub-procedure treating.The main diference is that nested language such aS pl/O language needs access chain while the nonnested lnaguage like C doesn’t need it since the C language does not support the nested definition of function but the pl/O lnaguage does. Key words_"access chain;sub-procedure treating;compiler