跳轉到內容

程式語言導論/繫結

來自華夏公益教科書,開放的書籍,開放的世界

原始檔包含許多需要確定其屬性的名稱。這些屬性的含義可能在程式生命週期的不同階段確定。此類屬性的示例包括與型別關聯的值集;變數的型別;編譯函式的記憶體位置;儲存在變數中的值等等。繫結是將屬性與名稱關聯的行為。繫結時間是程式生命週期中發生此關聯的時刻。

程式語言的許多屬性在建立過程中定義。例如,關鍵字的含義,如 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);
    }
  }
}

解釋性程式

華夏公益教科書