個別編譯與相關議題
個別編譯 Separate compilation
為何需要? 方便分工, 減少小幅修改程式時重新編譯所需的時間。
如何保証一致性? 各模組的實作者 (implementor) 與使用者 (user) 透過 header 檔間接檢查彼此的認知是否一致。
範例:
- 將 lt_scope.c 分成三個檔案, 分別編譯, 再聯結成可執行檔。
- 將 complex.c 分成三個檔案 complex.h, complex.c, test.c, 分別編譯, 再聯結成可執行檔。
- sitio.c 提供了文字模式遊標控制的 實作部分 (implementation); sitio.h 則提供了這些副程式的 介面部分 (interface)。 其他程式 (例如 dispath.c) 的程式設計師可以只參考 interface 即可呼叫 sitio.c 所提供的副程式。
- 與額外的程式庫聯: pi.c 使用 GNU Multipile Precision (gmp) 程式庫計算 pi 的近似值。
與額外的程式庫聯結, 例: 練習使用 GNU readline 界面, 並以 rlt.c 範例為骨架, 與你寫的 complex.c 聯結, 寫一個簡單的複數計算機。
作業: 使用 date.c 模組, 寫一個類似 UNIX 指令 cal 的程式。
變數的 life time 與 scope
請先閱讀 「程式語言」 講義的 變數篇 裡面相關兩節。 總結來說, 變數按照其知名度的高低可分為:
- 全域 (global scope; external linkage): 定義在所有副程式之外。 在所有的程式檔案中都看得到它。 使用前要用 extern 宣告。
- 檔案 (file scope; internal linkage): 定義在所有的副程式之外, 加上 static 關鍵字。 在同一個檔案中的所有 (在它之後定義的) 函數都看得到它。
- 區段 (block scope): 定義在一對大括弧內。 只有這對大括弧內 (在它之後的) 程式碼可以使用它。 (副程式內或複合敘述內)
請複習基本概念中的 "變數宣告" 與 "變數定義" 的差別。
因為 C 語言裡面, 函數不可以層層相疊地定義, 所以函數只有兩種 scope: global scope (一般函數皆是) 及 file scope (以 static 宣告的函數)。
作業
請解釋以下敘述:
- 被呼叫好幾次的副程式當中的一個自動變數, 其實是好幾個名字相同, "生存年代" 不同的變數。
- 遞迴的副程式當中的一個自動變數, 其實是好幾個名字相同, 而且曾經同時存在的變數。
- Free store 中要來的變數一律沒有名字。
Preprocessing -- 前置處理
以 "#" 放在一列的最左邊開頭的 "句子" 叫做 preprocessor directive, 由 preprocessor 處理。
Preprocessor 完全看不懂 C 程式, 它所有的動作都純粹是字串的處理 (代換, 刪除, 插入, ...) 而已。
#if 的用途: 選擇性地編譯 C 本文檔的某部分, 例如避免重複編譯, 根據不同的作業平臺編譯不同的部分, ..。
#define 的用途: 定義簡單的函數 (還有助憶名。 簡單, 已看過, 不談)
- 使用時機: 函數很短, 不值得建立 activation record 所花的工夫, 例如絕對值, 最大值, 最小值, ..。
- 定義時要注意: 多用括弧, 將參數與結果都包起來。 例:
#define hypotenuse(x, y) sqrt((x)*(x)+(y)*(y))
- 使用時要注意: 不要傳入有副作用的運算式, 例如:
abs(x++)
注意: 不要把 preprocessing 和程式的流程 (例如 #if 與 if) 混淆了。 Preprocessing 只是字串處理。 Preprocessing 執行完了之後才要開始編譯而已, 程式根本還沒有開始執行!
從前置處理到程式執行的完整過程 (以 此 為例)
- Preprocessor 處理 preprocessor directive。
- Compiler 將程式原始碼編譯為 object code (.o 或 .obj, 目的碼)
- Librarian 將多個 object files 聯結產生靜態程式庫檔 (.a 或 .lib) 或產生動態程式庫檔 (.so 或 .dll)
- Linker 將一個或多個 object 檔與靜態程式庫檔聯結, 產生可執行檔 (在 UNIX 系統下可以是任何名稱; 在 MS 系統下為 .exe 或 .com)
- Loader 將可執行檔載入記憶體並與動態程式庫 (.so 或 .dll) 聯結, 開始執行。 為何要有動態程式庫? 動態分享, 減少可執行檔所佔硬碟及記憶體空間
- 本頁最新版網址: https://frdm.cyut.edu.tw/~ckhung/b/c/sepcompile.php; 您所看到的版本: February 14 2012 10:32:25.
- 作者: 朝陽科技大學 資訊管理系 洪朝貴
- 寶貝你我的地球, 請 減少列印, 多用背面, 丟棄時做垃圾分類。
- 本文件以 Creative Commons Attribution-ShareAlike License 或以 Free Document License 方式公開授權大眾自由複製/修改/散佈。