编译原理:引论(三):程序设计语言基础

本文为《编译原理》(龙书) 的读书笔记 (1.6)

静态和动态的区别

在为一个语言设计一个编译器时,我们所面对的最重要的问题之一是编译器能够对一个程序做出哪些判定

  • 如果一个语言使用的策略支持编译器静态决定某个问题,那么我们说这个语言使用了一个静态(static)策略,或者说这个问题可以在编译时刻(compile time)决定
  • 一个只允许在运行程序的对候做出决定的策略被称为动态策略(dynamic policy) , 或者被认为需要在运行时刻(runtime)做出决定

我们需要注意的另一个问题是声明的作用域

  • 如果仅通过阅读程序就可以确定一个声明的作用域, 那么这个语言使用的是静态作用域(static scope) , 或者说词法作用域(lexical scope)
  • 否则,这个语言使用的是动态作用域(dynamic scope)。如果使用动态作用域,当程序运行时,同一个对 x x x 的使用会指向 x x x 的几个声明中的某一个

大部分语言( 比如 C 和 Java ) 使用静态作用域

名字和标识符

标识符(identifier)是一个字符串,通常由字母和数字组成。它用来指向一个实体

所有的标识符都是名字,但并不是所有的名字都是标识符。名字也可以是一个表达式。比如名字x.y可以表示x所指的一个结构中的字段y。这里xy是标识符。像x.y这样的复合名字称为受限名字(qualified name)

动态作用域

从技术上讲,如果一个作用域策略依赖于一个或多个只有在程序执行时刻才能知道的因素,它就是动态的。然而,术语动态作用域通常指的是下面的策略:对一个名字 x x x 的使用指向的是最近被调用但还没有终止且声明了 x x x 的过程中的这个声明

这种类型的动态作用域仅仅在一些特殊情况下才会出现。我们将考虑两个动态作用域的例子:

  • C预处理器中的宏扩展
  • 面向对象编程中的方法解析

例1.7
在图1-12给出的C程序中,标识符a是一个代表了表达式(x+ 1)的宏。但 x x x 到底是什么呢?我们不能够静态地解析 x x x

在这里插入图片描述

实际上,为了解析 x x x , 我们必须使用前面提到的普通的动态作用域规则。我们检查所有当前活跃的函数调用,然后选择最近调用的且具有一个对 x x x 的声明的函数。对 x x x 的使用就是指向这个声明

在图1-12的例子中,函数main首先调用函数bb有一个 x x x 的声明,因此b中的printf中的(x + 1)指向这个 x x x 。因此,打印出的值是2
b运行结束之后,函数c被调用,唯一可以被c访问的x是全局变量x。函数c中的printf语句打印的值是3

动态作用域解析对多态过程是必不可少的。所谓多态过程是指对于同一个名字根据参数类型具有两个或多个定义的过程

别名

引用调用或者其他类似的方法,会引起一个有趣的结果。有可能两个形式参数指向同一个位置,这样的变量称为另一个变量的别名(ailas)。结果是,任意两个看起来从两个不同的形式参数中获得值的变量也可能变成对方的别名

事实上,如果编译器要优化一个程序,就要理解别名现象以及产生这一现象的机制。在很多情况下我们必须在确认某些变量相互之间不是别名之后才可以优化程序
比如,我们可能确定x=2 是变量x唯一被赋值的地方。如果是这样,那么我们可以把对x的使用替换为对2 的使用。比如,把a = x +3 替换为较简单的a = 5 。但是,假设有另一个变量yx的别名。那么,一个赋值语句y = 4可能具有意想不到的改变x的值的效果。这可能也意味着把a = x +3 替换为a = 5 是一个错误

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值