值 之三 绑定

来源:互联网 发布:telnet连接 配置端口 编辑:程序博客网 时间:2024/05/16 05:12

绑定

在程序中常常靠名字操纵程序对象,以此编制有声有色的程序。只有当名字和存储对象结合在一起才能构成程序对象,所以,名字不等于程序对象,它只有通过绑定才能成为程序对象。

1,名字和绑定

把名字和存储对象联系起来叫做绑定,绑定时将标识符和可绑定体联系起来。所谓的可绑定体就是指能反映语义的存储块,如常量、变量的存储体、函数体等。

在一个程序的生命周期期间,一旦绑定不再改变叫做静态绑定,静态绑定一般是在运行之前完成(编译时做一部分,链接时做一部分,装载确立后再做完),反之,一个名字在不同时间绑定多个存储对象叫做动态绑定。还有一种介于动静之间的叫块结构绑定。

2,声明

声明指明了本程序用到的所有程序对象。实质上,它给出预想的束定集合(实现世界),即每个标识符和什么样的存储对象束定。声明的作用,一方面供翻译器处理时所需信息,一方面为人们阅读便于调试。对于类型语言,一般有显式声明部分或声明语句。强类型语言每个标识符都要显式声明。对于其它类型语言允许隐含声明。声明可以分为以下几类:

1)定义

   定义为标识符束定提供完整信息,使标识符可束定于确定的存储对象上。定义就是声明,而声明不完全等于定义。一般说来,一个标识符可以声明多次而定义只能一次。否则产生名字冲突。

2) 顺序声明与并行声明

       程序讲究的就是次序,所以声明一开始都有一个隐含约定:声明是顺序的,即后声明的声明符(declerator)可立即使用刚声明的声明符。如果把声明符集写作D则有顺序声明:

     D1 D2

        声明确立次序先D1D2(分号表示)。因此,D1可以影响到D2的声明

           并行声明不怕次序调换。ML语言中就有并行声明,其一般形式是:

     D1D2 D1  and  D2

       两个子声明D1D2是独立的,即它们确立相互无影响,确立先后不会改变声明的意图,因此,就不能立即声明立即用了。

   对于讲究副作用、次序的命令式语言是不会采用并行声明的。除非同一程序描述并行的子程序部分。而函数式、逻辑式因排除副作用,故可采用。

(3) 递归声明

    递归声明是标识符以自身束定的声明,一般形式是:

     D = D        //D是包含标识符D的声明符

     D1 = D2    //D1是间接递归或称相互递归

       D2 = D1

    递归声明通常限于类型、过程、函数、值定义。至少到目前还没有扩大到更大的方面,如类、模块、程序包、类属、异常等。

    有的语言采用自动递归,有的语言则由程序员显式指明递归,后者当有重名时程序员有主动性。

3,声明的作用域

在程序正文中声明有效的范围称为作用域。作用域由所在程序块起止符标识。声明自出了该声明符的句子(已经产生绑定),即开始生效,直至所在块的终止符,所以早期语言声明部分均在块的起始处。

4,绑定与环境

声明是给出预期的束定,而绑定总是在以前绑定过的标识符的基础上进行,即承认已有绑定。我们把以前的绑定集的作用域范围称为环境(environment),当然环境还包括系统预定义的字面量,关键字。一旦对某标识符作出束定,它也成为新环境的一部分。环境用以解释程序中的一切活动,例如有声明:

     const c=7

将标识符C与常整型存储对象绑定,其中放值7。完成绑定(确立)后,c就是常量程序对象'7'的指称。

     再如:

     var c Char

c就是字符变量的程序对象的指称,两个c绑定不同是它所在的环境不同,当然同一环境下, 同一标识符不能有两次绑定(请注意,同一程序同一标识符可声明多次为什么?)。环境是有效声明的集合(程序世界)

5,词法作用域和动态作用域

把程序正文给出的嵌套声明作用域叫词法作用域,嵌套块是词法子辈,被嵌套块是父辈,它们的作用域相互复盖,以最近原则束定。

词法作用域一般以上节介绍的运行时堆栈和堆栈帧实现。编译后的执行代码和全局量先入运行时堆栈成第一个堆栈帧。当程序执行进入子程序或块时,它的参数,局部变量另辟堆栈帧存放。当然还要包括子程序的返回地址(动态父辈,并且成动态链)和指示词法父辈的指针(静态链)。静态链以全名束定实现, 它提供了词法作用域描述。

每个程序的程序对象一旦交付编译,它的名字个数是确定的,唯独递归定义可在运行时创建无数个堆栈分配的对象。每次递归地调用本函数都要作新的存储分配形成新一层堆栈帧。新的存储块(堆栈帧)一直保留对参数和局部量的束定,直至该程序块出口。我们说这个堆栈帧是动态作用域

 

原创粉丝点击