編譯和鏈結

2021-07-02 19:57:48 字數 1812 閱讀 4568

平時,我們口頭上並不嚴格區分「編譯」(

compile

)與「鏈結」(

link

)這兩個專業術語。例如我們總是說「把那個

c檔案編譯成可執行檔案

......

」,寫成命令就是:

$gcc example.c

這個命令馬上給我們產生乙個「a.out」(如果程式沒有錯誤的話)。

實際上,整個工作至少要分成四個階段,分別由不同的程式完成:

第一階段:由預處理程式(unix的預處理程式通常是cpp)執行c原始檔的預處理指令;

第二階段:c編譯器把經過預處理的c**檔案編譯成彙編**檔案。

第三階段:彙編編譯器(gas)把彙編**檔案編譯成目標**檔案(以.o為字尾)。

第四階段:鏈結程式(ld)把所有目標**鏈結起來產生可執行檔案。

所以,編譯(包括第

一、二、三階段)和鏈結(第四階段)是兩回事。

為什麼搞得這麼複雜?這是因為c語言是用來進行大型專案開發的系統語言,它必須允許很多人合作開發乙個專案,所以,乙個c程式可以分開由很多個源**檔案組成,不一定非得把所有**都放在同乙個檔案裡。這樣就要求編譯過程必須分成某些步驟,因為既然源**由很多個檔案組成,那就是說每個單獨的原始檔都不可能包含所有的程式**,所以根本不可能要求編譯器僅僅根據其中某乙個c檔案就直接產生可執行檔案,它肯定要等到所有的**檔案都完成編譯才有可能輸出最後的執行檔案。

事實上我們以前編寫的程式就是由多個檔案組成的,main函式和其他我們自己定義的函式自然就是由我們自己來編寫,其他的一些函式,例如printf,我們一樣能使用,但我們從來沒有編寫過printf。像printf這些函式作為c語言標準庫的一部分,已經由其他人(通常是編譯器廠商)寫好了並編譯成庫檔案,我們的**編譯後只需和這些庫進行鏈結就可以產生可執行檔案。

從前面的討論我們大概明白c**經過編譯會產生目標**,這個目標**又是什麼呢?還記得我們把一些c**編譯成彙編**嗎?仔細觀察彙編檔案就不難得出結論,目標**其實已經是以機器碼的形式存在,只不過還有一些符號的位址需要鏈結時才能解決。舉個例子:

/*example c code*/

#include

int main(void)

$gcc –s test.c

$cat test.s

.section   .rodata

.lc0:

.string     「a=%d\n」

.text

.globl main

.type       mian, @function

main:

...movl       $.lco, (%esp)

movl       a, %eax

movl       %eax, 4(%esp)

call         printf

...編譯程式要做的事情之一就是把所有需要確定位址的符號($.lc0、a、printf)記錄下來,然後鏈結程式在找到它們的定義點之後通過計算給與合適的位址。當所有符號都有確定的位址時,鏈結程式就能夠產生可執行檔案。如果還有符號不能確定位址(找不到定義或重複定義)鏈結程式就會報錯。例如對上面的c程式:

$gcc test.c

馬上就有出錯資訊:undefined reference to 『a』。

因為我們根本沒有定義變數a,鏈結程式自然就不可能確定a的位址,於是出錯退出,最終的可執行檔案也無法生成。如果我們再寫乙個c檔案如下:

/*example c code 2*/

int a = 1;

執行:$gcc test.c test2.c

外部變數在test2.c中得到定義,鏈結程式可以確定a的位址,順利產生可執行檔案a.out。

編譯和鏈結

一般來說,無論是c c 首先要把原始檔編譯成中間 檔案,在windows下也就是 obj 檔案,unix下是 o 檔案,即 object file,這個動作叫做編譯 compile 然後再把大量的object file合成執行檔案,這個動作叫作鏈結 link 編譯時,編譯器需要的是語法的正確,函式與...

編譯和鏈結

在多道程式的實現中,要想使原始檔生成可執行檔案通常需要兩個步驟編譯和鏈結,其中編譯是指將原始檔編譯為中間 檔案,在linux中為 o檔案,其實質就是由c或c 等高階語言生成組合語言。生成可執行檔案,我們以編譯c c 為例,在windows中編譯生成的為.obj檔案,在linux unix中生成.o檔...

編譯和鏈結

編譯和鏈結 1 編譯 由編譯程式將使用者的源 編譯成若干個目標模組。3 載入 由引導程式將載入模組載入記憶體。編譯和鏈結都是為將使用者程式從硬碟上調入記憶體並將其轉換為可執行程式服務的。用編譯器時的compile就是在進行編譯,link就是鏈結,執行程式時可以看到。編譯可以理解為高階語言翻譯為計算機...