C編程的基本策略是使用程序將源代碼轉換為可執行文件,此文件包含可運行的機器語言代碼。C分兩步完成這一工作:編譯和鏈接。編譯器將源代碼轉換為中間代碼,連接器將此中間代碼與其他代碼相結合來生成可執行文件。C使用被划分為兩部分的這一方法使程序便於模塊化,你可以分別編譯各個模塊,然后使用連接器將編譯過的模塊結合起來。這樣,如何需要改變一個模塊,則不必重新編譯所有其他模塊。同時,鏈接器將您的程序與編譯的庫代碼結合起來。
中間文件的形式有多種選擇。最一般的選擇,同時也是我們這里講述的實現方式所采取的選擇,是將源代碼轉換為機器代碼。將結果放置在一個目標代碼文件(或簡稱目標文件)中(這里假定您的源代碼由單個文件組成)。雖然目標文件包含機器語言代碼,但該文件還不能運行。目標文件包含源代碼的轉換結果,但它還不是一個完整的程序。
目標代碼文件中所缺少的第一個元素是一種叫做啟動代碼(Start-up code)的東西,此代碼相當於您的程序和操作系統之間的接口。例如你可以在dos 或Linux下運行一個 IBM PC 兼容機,在兩種情況中硬件是相同的,所以都會使用同樣的目標代碼,但是 DOS與Linux要使用不用的啟動代碼,因為這兩種系統處理程序的方式不同的。
所缺少的第二個元素是庫例程的代碼。幾乎所有C程序都利用標准庫中所包含的例程(稱為函數)。例如,前面的concrete.c使用了函數printf()。目標代碼文件不包含這一函數的指令。實際代碼存儲在另一個稱為“庫”的文件中,庫文件中包含許多函數的目標代碼。
鏈接器的作用是將這3個元素(目標代碼、系統的標准啟動代碼和庫代碼)結合在一起,並將他們存放在單個文件,即可執行文件中。對庫代碼來說,鏈接器只從庫中提取您所使用的函數所需的代碼(見圖1.4所示)
簡而言之,目標文件和可執行文件都是由機器語言指令組成的。但目標文件只包含您所編寫的代碼轉換成的機器語言,而可執行文件還包含您所使用的庫例程以及啟動代碼。