在多道程式環境中,要想將乙個使用者源**變成乙個可以在記憶體中執行的程式,通常分為三個步驟:編譯、鏈結、載入。 (
1)編譯:由編譯程式將使用者的源**編譯成若干個目標模組。 (
2 (3
)載入:由引導程式將載入模組載入記憶體。
編譯和鏈結都是為將使用者程式從硬碟上調入記憶體並將其轉換為可執行程式服務的。用編譯器時的
compile
就是在進行編譯,
link
就是鏈結,執行程式時可以看到。
編譯可以理解為高階語言翻譯為計算機可以理解的二進位制**,即機器語言。
鏈結可以舉例解釋:乙個程式編譯後,在作業位址空間中所得到目標模組的起始位址通常是
0,假設在
1000
處有一條指令
load 1, 2500
,即將2500
單元處的資料取至暫存器
1中。在多道程式環境下,將程式載入記憶體時並不可能預先知道所編譯的模組應該放在記憶體的何處。假設程式被載入從
10000
開始的位址,此時的
2500
就應該變成了
12500
,這裡就出現問題了,需要修改指令中的相對位址,但此時如果採用動態鏈結就可以不用修改位址,靈活地解決這個問題了。
鏈結分三種:靜態鏈結、載入時動態鏈結、執行時動態鏈結,現在流行的是執行時動態鏈結,這種不僅可以回憶程式的載入過程,而且節省了大量的記憶體空間。
再來看c/c++
無論是c/c++
,首先要把原始檔編譯成中間**檔案,在
windows
下面就是
.obj
檔案,unix
、linux
下面就是
.o檔案,即
object file
,這個動作叫編譯(
compile
)。然後再把大量的
object file
合成執行檔案,這個動作叫作鏈結(
link)。
編譯時,編譯器需要的是語法的正確,函式與變數的宣告的正確。對於後者,通常是你需要告訴編譯器標頭檔案的所在位置(標頭檔案中應該只是宣告,而定義應該放在
c/c++
檔案中),只要所有的語法正確,編譯器就可以編譯出中間目標檔案。一般來說,每個原始檔都應該對應於乙個中間目標檔案(
.o檔案或是
.obj
檔案)。
鏈結時,主要是鏈結函式和全域性變數,所以,我們可以使用這些中間目標檔案(
.o檔案或是
.obj
檔案)來鏈結我們的應用程式。鏈結器並不管函式所在的原始檔,只管函式的中間目標檔案(
object file
),在大多數時候,由於原始檔太多,編譯生成的中間目標檔案太多,而在鏈結時需要明顯地指出中間目標檔名,這對於編譯很不方便,所以,我們要給中間目標檔案打個包,在
windows
下這種包叫「庫檔案」(
library file)
,也就是
.lib
檔案,在
unix
下,是archive file
,也就是
.a檔案。
總而言之,鏈結就是那些目標檔案之間相互鏈結自己所需要的函式和全域性變數,而函式可能**於其他目標檔案或庫檔案。
總結一下,原始檔首先會生成中間目標檔案,再由中間目標檔案生成執行檔案。在編譯時,編譯器只檢測程式語法,和函式、變數是否被宣告。如果函式未被宣告,編譯器會給出乙個警告,但可以生成
object file
。而在鏈結程式時,鏈結器會在所有的
object file
中找尋函式的實現,如果找不到,那到就會報鏈結錯誤碼(
linker error
),在vc
下,這種錯誤一般是:
link 2001
錯誤,意思是說,鏈結器未能找到函式的實現,需要指定函式的
object file
。
編譯和鏈結的區別
在多道程式環境中,要想將乙個使用者源 變成乙個可以在記憶體中執行的程式,通常分為三個步驟 編譯 鏈結 載入。1 編譯 由編譯程式將使用者的源 編譯成若干個目標模組。2 3 載入 由引導程式將載入模組載入記憶體。編譯和鏈結都是為將使用者程式從硬碟上調入記憶體並將其轉換為可執行程式服務的。用編譯器時的 ...
編譯和鏈結的區別
1 編譯 由編譯程式將使用者的源 編譯成若干個目標模組。3 載入 由引導程式將載入模組載入記憶體。編譯和鏈結都是為將使用者程式從硬碟上調入記憶體並將其轉換為可執行程式服務的。用編譯器時的compile就是在進行編譯,link就是鏈結,執行程式時可以看到。編譯可以理解為高階語言翻譯為計算機可以理解的二...
編譯和鏈結的區別
編譯和鏈結的區別 1 編譯 由編譯程式將使用者的源 編譯成若干個目標模組。3 載入 由引導程式將載入模組載入記憶體。編譯和鏈結都是為將使用者程式從硬碟上調入記憶體並將其轉換為可執行程式服務的。用編譯器時的compile就是在進行編譯,link就是鏈結,執行程式時可以看到。編譯可以理解為高階語言翻譯為...