程序语言的静态作用域和动态作用域

来源:互联网 发布:淘宝q币充值在哪 编辑:程序博客网 时间:2024/04/29 13:07

1. [嵌套]首先我们看一段程序:

#include <stdio.h>
int x= 5;
int f(){
return x;
}


int g(){
int x = 1;
return f();
}

int main(int argc,char*argv[]){
        printf(
"%d ",g());
}
 程序的输出会是1,还是5呢?答案是5,那原因是?
C语言采用的是静态作用域,即词法作用域,变量与值的绑定是通过检查程序的正文,在编译时期完成的,而与程序的运行流程无关。它扫描程序正文,选取最近遇到的那个绑定。

在采用动态作用域的语言里,变量与值的绑定是依赖于程序执行流程的,它是选取在运行的过程中所遇到的最近绑定。象上面的例子,如果C语言采用动态作用域的话,那输出结果将是1。

动态作用域易于实现,它只需顺势查找栈帧,查到谁,谁就和自己绑定。另外,有了动态作用域,可以随时拦截,改变程序的行为。在灵活的同时,随之而来的就是麻烦。为了确定程序的行为,必须仔细查看程序的具体执行流程,稍不小心就有可能引入bug。

静态作用域:包括C语言在内和它的同类的语言在内的大多数的语言使用静态作用域。C语言的作用域规则是基于程序结构的,一个声明的作用域由该声明在程序中出现的位置隐含地决定。稍后出现的语言,比如C++、Java和C#,也通过诸如public、private和protected等关键字的使用,提供了对作用域的明确控制。

动态作用域:如果一个作用域策略依赖于一个或多个只有在程序执行的时刻才能知道的因素,它就是动态的。

2. 静态作用域

典型:C, C++, Python, Java, JavaScript, Lua,大多数现在程序设计语言都是采用静态作用域规则。

静态作用域又叫做词法作用域,使用词法作用域的变量叫词法(lexical)变量。 词法变量都有一个确定的作用域和不确定的生存期。 词法变量的作用域可以是一个函数或block,使得其在这段代码区域内都有效。 但是词法变量的生存期取决于该变量需要引用(reference)多久(?)。

词法作用域里,对于函数体中的一个符号,不会逐层检查函数的调用链,而是检查函数定义时的外部环境,即捕捉的是函数定义时该符号的绑定。

3. 动态作用域

典型:Emacs Lisp, Common Lisp(两种都有), Perl(两种都有)。

使用动态作用域的变量叫做动态(dynamic)变量,有时也叫做特殊(special)变量。 动态变量具有不确定的作用域,只取决于在什么地方绑定它。 同时从绑定开始,到绑定时的代码段执行完毕,这就是动态变量的生存期。

动态作用域里,函数执行遇到一个符号,会由内向外逐层检查函数的调用链,并打印第一次遇到的那个绑定的值。显然,最外层的绑定即是全局状态下的那个值。


0 0