學習筆記之編譯和鏈結

2021-09-06 20:12:59 字數 1563 閱讀 4974

#include

int main(int argc,char **argv)

在linux下,使用gcc來編譯helloworld 程式時,只需使用最簡單的命令:

& gcc hello.cpp -o a

或$ gcc hello.cpp;  $./a.out

即可在螢幕上輸出hello world

事實上,上述過程可以分解為4個步驟,分別是預處理(prepressing)、編譯(compilation)、彙編(assembly)和鏈結(linking),如下圖所示:

1、預編譯

首先是源**檔案hello.c和相關的標頭檔案,如stdio.h等被預編譯器cpp預編譯成乙個.i檔案。對於c++程式來說,它的源**檔案的副檔名可能是.cpp或.cxx,標頭檔案的副檔名可能是.hpp,而預編譯後的副檔名是.ii。第一步預編譯後的副檔名是.ii。第一步預編譯的過程相當於如下命令(-e表示只進行預編譯):

$ gcc -e hello.c -o hello.i

或者:$ cpp hello.c > hello.i

預編譯過程主要處理那些原檔案中以「#」開始的預編譯指令。比如"#include"、"#define"等,主要處理規則如下:

>將所有的"#define"刪除,並展開所有的巨集定義。

>處理所有條件預編譯指令,比如"#if"、"#ifdef"、"#elif"、"#else"、"#endif"。

>處理"#include"預編譯指令,將被包含的檔案插入到該預編譯指令的位置。注意,這個過程是遞迴進行的,也就是說被包含的檔案可能包含其它的檔案。

>刪除所有的注釋"//"和"/**/"。

>新增行號和檔名標識,比如#2 "hello.c" 2,以便於編譯時編譯器產生除錯用的行號資訊及用於編譯時產生編譯錯誤或警告時能夠顯示行號。

>保留所有#pragma 編譯器指令,因為編譯器需要使用。

2、編譯

編譯過程就是把預處理完的檔案進行一系列詞法分析、語法分析、語義分析及優化後產生相應的彙編**檔案,這個過程是整個程式構建的核心部分。上例的編譯部分相當於:

3、彙編

彙編器是將彙編**轉變成機器可以執行的指令,每乙個彙編語句幾乎都對應一條機器指令。所以彙編器的彙編過程相對於編譯器比較簡單,他沒有複雜的語法,也沒有語義,也不需要做指令優化,只是根據彙編指令和機器指令的對照表一一翻譯就可以了。上例的彙編過程可以用彙編器as來完成:

$ as hello.s -o hello.o

或者:$ gcc -c hello.s -o hello.o

或者使用gcc命令從c源**檔案開始,經過預編譯、編譯和彙編直接輸出目標檔案(object file):

$ gcc -c hello.c -o hello.o

4、鏈結

先總結至此,後續補充.......

編譯和鏈結

一般來說,無論是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 如果程式沒有錯誤的話 實際上,整個工作至少要分成四個階段,分別由不同的程式完成 第...