C程式編譯過程

2021-07-06 08:01:41 字數 3257 閱讀 5560

接觸程式設計還在麼長時間,還沒有好好理解下一段**從.c到可執行程式的過程。

先看一下gcc的常用引數:

[引數詳解] 

-c 只啟用預處理,編譯,和彙編,也就是他只把程式做成obj檔案 

例子用法: 

gcc 

-c hello.c 

他將生成.o的obj檔案 

-s 只啟用預處理和編譯,就是指把檔案編譯成為彙編**。 

例子用法 

gcc 

-s hello.c 

他將生成.s的彙編**,你可以用文字編輯器察看 

-e 只啟用預處理,這個不生成檔案,你需要把它重定向到乙個輸出檔案裡 

面. 例子用法: 

gcc 

-e hello.c 

pianoapan.txt 

gcc 

-e hello.c 

| more 

慢慢看吧,乙個hello 

word 

也要與處理成800行的** 

-o 制定目標名稱,預設的時候,gcc 

編譯出來的檔案是a.out,可以用-o指定生成的檔案的名稱

例子用法 

gcc 

-o hello.exe 

hello.c 

(哦,windows用習慣了) 

gcc 

-o hello.asm 

-s hello.c 

-g 只是編譯器,在編譯的時候,產生除錯資訊。使用objdump -ds hello《可執行檔案》 可以得到反彙編**,其中會帶有對應行c**

現在來簡單總結一下。以簡單的hello world為例。

#include #define num 10

/* hello world */

int main(int argc, char* argv)

通常我們使用gcc來生成可執行程式,命令為:gcc hello.c,預設生成可執行檔案a.out

其實編譯(包括鏈結)的命令:gcc hello.c 可分解為如下4個大的步驟:

再來一張圖:

1.       預處理(preproceessing)

預處理的過程主要處理包括以下過程:

通常使用以下命令來進行預處理:

gcc -e hello.c -o hello.i

引數-e表示只進行預處理 , -o 是引數,後面需要跟輸出的檔名,如果不跟,那麼預處理後的**就會列印在終端上,-o就表示輸出到某個檔案中,類似於重定向。

或者也可以使用以下指令完成預處理過程

cpp hello.c > hello.i      /*  cpp – the c preprocessor  */

直接cat hello.i 你就可以看到預處理後的**

2.       編譯(compilation)

編譯過程就是把預處理完的檔案進行一系列的詞法分析,語法分析,語義分析及優化後生成相應的彙編**。

$gcc –s hello.i –o hello.s

或者$ /usr/lib/gcc/i486-linux-gnu/4.4/cc1 hello.c

注:現在版本的gcc把預處理和編譯兩個步驟合成乙個步驟,用cc1工具來完成。gcc其實是後台程式的一些包裝,根據不同引數去呼叫其他的實際處理程式,比如:預編譯編譯程式cc1、彙編器as、聯結器ld

3.       彙編(assembly)

彙編器是將彙編**轉變成機器可以執行的命令,每乙個彙編語句幾乎都對應一條機器指令。彙編相對於編譯過程比較簡單,根據彙編指令和機器指令的對照表一一翻譯即可。

$ gcc –c hello.c –o hello.o

或者$ as hello.s –o hello.co

由於hello.o的內容為機器碼,不能以普通文字形式的檢視(vi 開啟看到的是亂碼)。

gcc hello.c -o hello.o??? 是什麼情況呢?   檔案大小和上面的不一樣

4.       鏈結(linking)

通過呼叫鏈結器ld來鏈結程式執行需要的一大堆目標檔案,以及所依賴的其它庫檔案,最後生成可執行檔案。

ld -static crt1.o crti.o crtbegint.o hello.o -start-group -lgcc -lgcc_eh -lc-end-group crtend.o crtn.o (省略了檔案的路徑名)。

-static表示靜態鏈結

helloworld的大體編譯和鏈結過程就是這樣了,那麼編譯器和鏈結器到底做了什麼呢?

編譯過程可分為6步:掃瞄(詞法分析)、語法分析、語義分析、源**優化、**生成、目標**優化。

詞法分析:掃瞄器(scanner)將源代的字串行分割成一系列的記號(token)。lex工具可實現詞法掃瞄。

語法分析:語法分析器將記號(token)產生語法樹(syntax tree)。yacc工具可實現語法分析(yacc: yet another compiler compiler)。

語義分析:靜態語義(在編譯器可以確定的語義)、動態語義(只能在執行期才能確定的語義)。

源**優化:源**優化器(source code optimizer),將整個語法書轉化為中間**(intermediate code)(中間**是與目標機器和執行環境無關的)。中間**使得編譯器被分為前端和後端。編譯器前端負責產生機器無關的中間**;編譯器後端將中間**轉化為目標機器**。

目標**生成:**生成器(code generator).

目標**優化:目標**優化器(target code optimizer)。

鏈結的主要內容是把各個模組之間相互引用的部分處理好,使得各個模組之間能夠正確地銜接。

鏈結的主要過程包括:位址和空間分配(address and storage allocation),符號決議(symbol resolution),重定位(relocation)等。

鏈結分為靜態鏈結和動態鏈結。

靜態鏈結是指在編譯階段直接把靜態庫加入到可執行檔案中去,這樣可執行檔案會比較大。

動態鏈結則是指鏈結階段僅僅只加入一些描述資訊,而程式執行時再從系統中把相應動態庫載入到記憶體中去。

靜態鏈結的大致過程如下圖所示:

static linking

C程式編譯過程

題記 前幾天去華為面試實習生,面試官問了個問題,讓我說出乙個程式的詳細編譯過程,當時磕磕絆絆說了一堆東西,事後自己都不知道當時說了什麼,慚愧。c語言編譯過程 編譯,編譯程式讀取源程式 字元流 對之進行詞法和語法的分析,將高階語言指令轉換為功能等效的彙編 再由匯程式設計序轉換為機器語言,並且按照作業系...

C 程式編譯過程

首先是編譯過程整體簡介 編譯過程主要分為 4個過程 1 編譯預處理 預編譯程式完成的工作,可以說成是對源程式的 替換 工作。經過這個過程,生成乙個沒有巨集定義 沒有條件編譯指令 沒有特殊符號的輸出檔案。2 編譯 優化階段 通過詞法分析 語法分析,在確認所有的指令都符合語法規則之後,將其翻譯成等價的中...

C程式編譯過程

gcc編譯c 會有四個階段 預處理 將c 中的標頭檔案和巨集進行處理 彙編 把彙編 轉化成機器指令,並以特定的二進位制格式輸出儲存在 o這樣的目標檔案中 流程圖 參考閱讀 3.c程式分析 gcc e hello.c o hello.i 預處理 gcc s hello.i o hello.s 編譯 g...