【C语言】源代码的编译过程
一、引言
我們平常編寫C語言程序都是使用集成開發(fā)環(huán)境(IDE),這樣的IDE通常是將編譯和鏈接過程合并成一步完成,稱為構(gòu)建(Build)。這樣對開發(fā)者雖然比較友好,但同時由于集成開發(fā)環(huán)境運行時掩蓋了程序運行機制與機理,導(dǎo)致基礎(chǔ)開發(fā)者并不知道從C源代碼到二進(jìn)制可執(zhí)行文件生成中間到底經(jīng)歷哪些過程呢?接下來就來探索一下其中各個過程具體做了哪些工作。
二、C源代碼的編譯過程
c程序的基本編譯過程具體如下圖1和圖2所示:
源代碼.c文件和相關(guān)頭文件被預(yù)編譯器預(yù)編譯成一個.i文件;
對于C++程序而言,一般是.cpp文件和頭文件,預(yù)編譯成.ii文件
預(yù)處理相當(dāng)于根據(jù)預(yù)處理指令組裝新的C/C++程序。經(jīng)過預(yù)處理,會產(chǎn)生一個沒有宏定義,沒有條件編譯指令,沒有特殊符號的輸出文件,這個文件的含義同原本的文件無異,只是內(nèi)容上有所不同。
//gcc進(jìn)行預(yù)編譯: gcc -E hello.c -o hello.i具體工作:
1.刪除所有“#define”,并展開所有宏定義(進(jìn)行文本替換)
2.處理“#include”預(yù)編譯指令,遞歸展開被包含的文件并插入到該預(yù)編譯指令位置
3.處理“#if”、“#ifdef”、“#elif”、“endif”等條件編譯指令
4.刪除所有的注釋(“//”和“/* */”)
5.添加行號和文件名標(biāo)識,以便編譯時編譯器產(chǎn)生調(diào)試用的行號信息及用于編譯時產(chǎn)生編譯錯誤或警告時能夠顯示行號
6.保留所有的“#program”指令,因為編譯器編譯時需要使用它們
- 編譯
將.i文件翻譯成匯編代碼.s文件(在windows中,通常使用.asm便是匯編文件)
具體工作:
1.詞法分析
(對構(gòu)成源程序的字符串從左到右進(jìn)行掃描分析,根據(jù)語言的詞法規(guī)則識別一個一個具有獨立意義的單詞,例如:保留字(begin、end、for、while等)、標(biāo)識符、常數(shù)、運算符、界符等)
2.語法分析
(根據(jù)語言的語法規(guī)則,把單詞符號串分解成各類語法單位,如短語、子句、句子、程序段等,并檢查各種語法單位在語法結(jié)構(gòu)上的正確性)
3.語義分析
(對每種語法單位進(jìn)行靜態(tài)語義(靜態(tài)語義指程序在語義上要遵守的規(guī)則)審查,然后分析其含義,并用另一種語言形式來描述這種語義)
4.中間代碼生成及優(yōu)化
5.生成匯編代碼文件(生成指令)
- 匯編
通過匯編器as將編譯完的匯編代碼文件翻譯成機器指令,并生成可重定位目標(biāo)程序的.o文件,該文件為二進(jìn)制文件,字節(jié)編碼是機器指令。
- 鏈接
通過鏈接器將一個個目標(biāo)文件(或許還會有庫文件)鏈接在一起生成一個完整的可執(zhí)行程序。
具體工作:
1.合并段和符號表
2.符號解析
3.分配地址和空間
4.符號重定義
- 執(zhí)行
具體工作:
1.創(chuàng)建虛擬內(nèi)存空間和物理內(nèi)存(創(chuàng)建PCB)
2.加載指令和數(shù)據(jù)
3.將入口地址寫入下一條指令寄存器
三、編譯程序、翻譯程序、匯編程序、解釋程序的辨析
-
翻譯程序
將用匯編語言或高級語言編寫的程序轉(zhuǎn)換成等價的機器語言程序,執(zhí)行這種轉(zhuǎn)換功能的程序統(tǒng)稱為翻譯程序 -
匯編程序
源程序為匯編語言,目標(biāo)程序為機器語言的翻譯程序 -
編譯程序
源程序為高級語言編寫的程序,目標(biāo)程序為匯編語言或機器語言的翻譯程序 -
解釋程序
接受某個語言的程序并立即運行這個源程序。它的工作模式是一個個的獲取、分析并執(zhí)行源程序語句,一旦第一個語句分析結(jié)束,源程序便開始運行并且產(chǎn)生結(jié)果,它特別適合程序員以交互方式工作的情況,即希望在獲取下一個語句之前了解每個語句的執(zhí)行結(jié)果,允許執(zhí)行時修改程序。
編譯方式和解釋方式實現(xiàn)高級語言的編譯的區(qū)別:
在解釋方式下,并不生成目標(biāo)代碼程序,而是直接執(zhí)行源程序本身
總結(jié)
以上是生活随笔為你收集整理的【C语言】源代码的编译过程的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: html 各种字符 换位键,excel替
- 下一篇: 如何自动执行Excel的多次替换--Ex