了解編譯和鏈結

2022-07-11 07:48:12 字數 1706 閱讀 5475

在步入工作崗位之後,重新對程式設計是個什麼過程進行了了解

簡單的來說,我們平常所寫的**經過編譯和鏈結之後生成可執行檔案,下面就編譯和鏈結兩個過程分別討論

編譯階段

編譯階段需要的素材就是你的原始檔,把原始檔經過一系列神奇的編譯操作變成目標檔案就是我們的目的,也就是linux系統下使用gcc -c得到的目標檔案

預處理簡單來說就是巨集的展開和標頭檔案的包含,把#include的東西全都複製進去,把檔案變大,但是語言本質並沒有改變,也就是說你的c還是原來的c

程式語言到組合語言就是編譯器做的工作了,乙個好的編譯器在這裡會下很大的功夫。

可以這麼理解,組合語言和機器語言基本是等價的,區別只不過是組合語言還是給人看的,機器語言已經不是給人看的了是給機器看的(當然你要是精通機器語言也是吼的),為什麼這麼說?每一條組合語言都有機器語言去對應,每乙個彙編命令都是一串二進位製碼

編譯的結果是生成目標檔案,每乙個編譯單元生成對應的乙個目標檔案,這裡還是可以參考linux系統下的gcc -c,使用這條命令的時候會把每個.c檔案的檔名拿來直接生成對應的.o檔案(就是helloworld.c->helloworld.o)

鏈結階段

上圖是各個檔案相互轉化的圖。目標檔案可以直接生成可執行檔案,也可以做成動態庫或者靜態庫,靜態庫可以鏈結另乙個靜態庫變成乙個更大的庫。諸如此類的轉化

提到鏈結就有很多熟悉的名詞和概念要提

靜態庫

靜態庫在程式編譯的時候會被鏈結到目標**當中,所以在程式執行的時候就不再需要靜態庫啦,相當於可執行程式把靜態庫包含了。

動態庫

與靜態庫相對的動態庫,在程式編譯的時候並不會被鏈結到目標**當中,而是在程式執行的時候才被載入,因此在程式執行的時候還需要動態庫的存在,這就是在執行一些軟體的時候你會看到乙個警告框,提醒你缺少某個.dll檔案的原因

靜態鏈結

靜態鏈結是指在鏈結的過程中直接將需要執行的**(函式)拷貝到呼叫的地方,在程式執行的時候不在需要依賴鏈結的庫,也不用帶著庫一起發布,程式就可以獨立執行,但是程式的體積可能會大一些,因為會把一些**塞進可執行程式裡面

動態鏈結

與靜態鏈結相對的,動態鏈結不會在鏈結的過程中把**拷貝到呼叫的地方,動態鏈結會把呼叫的地方記錄一些符號和引數(例如生成乙個函式對應的符號),在程式執行到這個呼叫的地方的時候,可執行程式會把這些符號和引數傳遞給作業系統,作業系統會根據需要把對應的動態庫載入到記憶體,然後可執行程式就可以去這段記憶體中尋找動態庫中的**,同時因為載入到共享的記憶體中可以供多個程式共同使用,這就是所謂的執行時鏈結。相比靜態鏈結來說,由於不向可執行程式中拷貝**,使得程式的體積在一定意義上減小了。因為動態鏈結將庫載入到記憶體,省去了在各個程式中的拷貝,減少了磁碟的占用,可以讓多個程式共享使用。但是缺點是載入需要一定的時間,可能會影響一定的效能

總結

一般來講,靜態鏈結和靜態庫對應使用,動態鏈結和動態庫對應使用。據說有方法可以有別的使用方法,這裡就不討論了,有興趣的可以搜尋下

編譯和鏈結

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

編譯和鏈結

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

編譯和鏈結

平時,我們口頭上並不嚴格區分 編譯 compile 與 鏈結 link 這兩個專業術語。例如我們總是說 把那個 c檔案編譯成可執行檔案 寫成命令就是 gcc example.c 這個命令馬上給我們產生乙個 a.out 如果程式沒有錯誤的話 實際上,整個工作至少要分成四個階段,分別由不同的程式完成 第...