跳转到内容

编程语言导论/绑定

来自维基教科书,开放的书籍,开放的世界

源文件包含许多需要确定其属性的名称。这些属性的含义可能在程序生命周期的不同阶段确定。此类属性的示例包括与类型关联的值集;变量的类型;编译函数的内存位置;存储在变量中的值等等。绑定是将属性与名称关联的行为。绑定时间是程序生命周期中发生此关联的时刻。

编程语言的许多属性在创建过程中定义。例如,关键字的含义,如 C 中的whilefor,或者 Java 中的整数数据类型的大小,是在语言设计时定义的属性。另一个重要的绑定阶段是语言实现时间。C 中的整数大小,与 Java 不同,在 C 设计时并没有定义。此信息由编译器的实现确定。因此,我们说 C 中的整数大小是在语言实现时间确定的。

程序的许多属性是在编译时确定的。其中,最重要的属性是类型静态类型的语言中。每当我们在 C 或 Java 中将变量标注为整数,或者每当编译器推断出 Haskell 或 SML 中的变量具有整数数据类型时,此信息将从此以后用于生成与该变量相关的代码。静态分配变量的位置,[激活记录]的布局以及控制流图静态编译的程序是其他在编译时定义的属性。

如果程序使用外部库,则外部函数的地址将只在链接时间知道。正是在这一刻,运行时环境找到 C 程序调用的printf函数的位置,例如。但是,程序中使用的绝对地址只会在加载时间知道。在那一刻,我们将在内存中拥有可执行程序的镜像,所有依赖关系都已由加载器解决。

最后,有些属性只有在程序执行后才能知道。存储在变量中的实际值可能是这些属性中最重要的。在动态类型语言中,我们只会在程序执行期间知道变量的类型。提供某种形式的晚绑定的语言只会在运行时让我们知道函数调用的目标,例如。

例如,让我们看一下下面用 C 实现的程序。在第 1 行中,我们定义了三个名称:intix。其中一个代表类型,而另外两个代表两个变量的声明。C 语言规范定义了关键字int的含义。与该规范相关的属性是在定义语言时绑定的。还有一些其他属性没有包含在语言定义中。一个例子是int类型的取值范围。这样,编译器的实现可以选择一个最适合特定机器的int类型的特定范围。第一行中变量ix的类型是在编译时绑定的。在第 4 行中,程序调用函数do_something,其定义可能在另一个源文件中。此引用在链接时解决。链接器尝试找到函数定义以生成可执行文件。在加载时,就在程序开始运行之前,maindo_somethingix 的内存位置被绑定。一些绑定在程序运行时发生,即在运行时。一个例子是在程序执行期间赋予ix的可能值。


int i, x = 0;
void main() {
  for (i = 1; i <= 50; i++)
    x += do_something(x);
}

相同的实现也可以用 Java 完成,如下所示

public class Example {
  int i, x = 0;

  public static void main(String[] args) {
    for (i = 1; i <= 50; i++) {
      x += do_something(x);
    }
  }
}

解释性程序

华夏公益教科书