n熟練掌握Linux GCC的使用操作方法
1.2實(shí)驗(yàn)內(nèi)容
n綜合運(yùn)用Linux GCC的技巧操作。
n利用GCC編譯器編譯程序
1、實(shí)驗(yàn)要求:
編寫一個(gè)應(yīng)用程序,使用gcc進(jìn)行編譯,并分別使用-o,-g佃迄,-static泼差,-O2等選項(xiàng),了解這些選項(xiàng)的作用呵俏。
2堆缘、實(shí)驗(yàn)器材:
軟件:
安裝了ubuntu的VMware虛擬機(jī)。
硬件:
PC機(jī)一臺(tái)普碎。
3吼肥、背景知識(shí):
ügcc的概念:
GCC(GNU CompilerCollecti on,GNU編譯器套裝)麻车,是一套由GNU開發(fā)的編程語言編譯器缀皱。它是一套以GPL及LGPL許可證所發(fā)行的自由軟件,也是GNU計(jì)劃的關(guān)鍵部分动猬,亦是自由的類Unix及蘋果電腦MacOSX操作系統(tǒng)的標(biāo)準(zhǔn)編譯器啤斗。GCC原名為GNU C語言編譯器,因?yàn)樗局荒芴幚鞢語言枣察。GCC很快地?cái)U(kuò)展争占,變得可處理C++燃逻。之后也變得可處理For tr an序目、Pascal、Obj ecti v e-C伯襟、Jav a,以及Ada與其他語言猿涨。我們使用的gcc命令主要是用于處理c語言程序。
ügcc的執(zhí)行過程:
雖然我們稱Gcc是C語言的編譯器姆怪,但使用gcc由C語言源代碼文件生成可執(zhí)行文件的過程不僅僅是編譯的過程叛赚,而是要經(jīng)歷四個(gè)相互關(guān)聯(lián)的步驟∶預(yù)處理(也稱預(yù)編譯,Preprocessing)稽揭、編譯( Compilation)俺附、匯編( Assembly)和鏈接( Linki ng)。命令gcc首先調(diào)用cpp進(jìn)行預(yù)處理溪掀,在預(yù)處理過程中事镣,對(duì)源代碼文件中的文件包含( i
ncl ude)、預(yù)編譯語句(如宏定義define等)進(jìn)行分析揪胃。接著調(diào)用cc1進(jìn)行編譯璃哟,這個(gè)階段根據(jù)輸入文件生成以.o為后綴的目標(biāo)文件。匯編過程是針對(duì)匯編語言的步驟喊递,調(diào)用as進(jìn)行工作随闪,一般來講,.S為后綴的匯編語言源代碼文件和匯編骚勘、.s為后綴的匯編語言文件經(jīng)過預(yù)編譯和匯編之后都生成以.o為后綴的目標(biāo)文件铐伴。當(dāng)所有的目標(biāo)文件都生成之后,gcc就調(diào)用ld來完成最后的關(guān)鍵性工作,這個(gè)階段就是連接盛杰。在連接階段挽荡,所有的目標(biāo)文件被安排在可執(zhí)行程序中的恰當(dāng)?shù)奈恢茫瑫r(shí)即供,該程序所調(diào)用到的庫函數(shù)也從各自所在的庫中連到合適的地方定拟。以上這些過程是gcc內(nèi)部實(shí)現(xiàn)的機(jī)制,實(shí)際使用中逗嫡,上述過程可以又通過gcc的選項(xiàng)實(shí)現(xiàn)青自,具體方法請(qǐng)通過實(shí)驗(yàn)體會(huì)。
4驱证、實(shí)驗(yàn)步驟
ü先用vim編輯hello.c文件延窜,內(nèi)容如圖所示:
圖1vim編寫hello.c
ügcc命令的一般格式為:gcc[選項(xiàng)]要編譯的文件[選項(xiàng)][目標(biāo)文件]。
下面使用命令gcchello.c–ohello抹锄,編譯hello.c逆瑞,并生成可執(zhí)行文件hello,
圖2直接生成可執(zhí)行文件hello
注意:上面的命令將.c文件生成了可執(zhí)行文件伙单,實(shí)際上是將預(yù)處理获高、編譯、匯編吻育、連接一步完成念秧,下面我們將介紹四個(gè)流程分別做了什么工作。
ü使用–E選項(xiàng)布疼,執(zhí)行預(yù)處理工作摊趾。使用命令gcc–E hello.c–o hello.i對(duì)hello.c進(jìn)行預(yù)處理,生成文件hello.i游两,如圖所示:
圖3使用-E選項(xiàng)
使用命令cat
hello.i查看hello.i文件的內(nèi)容砾层,如圖5-4所示,可以看到頭文件
stdio.h中包含的內(nèi)容替換掉了原先代碼中的#include贱案。
圖4查看文件hello.i內(nèi)容
ü使用–S選項(xiàng)肛炮,執(zhí)行編譯處理工作。使用命令gcc–S hello.i–o hello.s對(duì)hello.i進(jìn)行編譯轰坊,生成匯編文件hello.s铸董,如圖所示:
圖5使用-S選項(xiàng)
使用命令cat
hello.s查看hello.s文件的內(nèi)容,如圖5-6所示肴沫,可以看到原來的
c語言代碼已被轉(zhuǎn)化為匯編代碼粟害。
圖6查看文件hello.s內(nèi)容
ü使用–c選項(xiàng),執(zhí)行編譯工作颤芬。使用命令gcc–chello.s–o
hello.o對(duì)hello.s進(jìn)行匯編悲幅,生成目標(biāo)文件hello.o套鹅,如圖所示:
圖7執(zhí)行使用-c選項(xiàng)
ü使用命令gcc hello.o–o hello將hello.o鏈接庫,生成可執(zhí)行文件hello汰具,如圖
所示卓鹿,以上四個(gè)步驟就對(duì)應(yīng)了gcc執(zhí)行過程的四個(gè)基本步驟,下面我們來看看gcc其他一些重要的選項(xiàng)留荔。
圖8連接生成可執(zhí)行文件
ü使用–static選項(xiàng)吟孙,靜態(tài)鏈接庫。使用命令gcchello.c–ohello和gcchello.c–static–ohello1分別生成兩個(gè)可執(zhí)行文件hello和hello1聚蝶。頭一個(gè)文件hello是不加-static選項(xiàng)杰妓,默認(rèn)是鏈接動(dòng)態(tài)庫生成的,如圖所示碘勉,試比較鏈接動(dòng)態(tài)庫生成的文件hello和鏈接靜態(tài)庫生成的文件hello1的大小巷挥。
圖9使用-static選項(xiàng)
可以看到靜態(tài)鏈接庫的可執(zhí)行文件hello1要比動(dòng)態(tài)鏈接庫的文件hello大很多,他們的執(zhí)行效果是一樣的验靡。
注意:要使動(dòng)態(tài)鏈接庫的可執(zhí)行文件能夠在機(jī)器上運(yùn)行倍宾,必須保證系統(tǒng)中安裝有相關(guān)的動(dòng)態(tài)鏈接庫,這些庫一般在/lib目錄下胜嗓。
ü使用–g選項(xiàng)高职,在可執(zhí)行程序中包含標(biāo)準(zhǔn)調(diào)試信息。使用命令gcc–ghello.c–o
hello2生成包含調(diào)試信息的文件hello2兼蕊,如圖所示初厚,帶有調(diào)試信息的可執(zhí)行文件可以使用gdb調(diào)試器進(jìn)行調(diào)試件蚕,gdb的具體用法將在下節(jié)討論孙技。
圖10使用-g選項(xiàng)
ü使用–D選項(xiàng),在編譯時(shí)進(jìn)行宏定義排作。使用命令gcc–DLINUXhello.c–o
hello3生成定義了宏LINUX的的可執(zhí)行文件hello3牵啦,如圖所示,將hello3和原可執(zhí)行文件hello進(jìn)行比較妄痪。
圖11修改源碼哈雏,注釋第三行代碼
圖12使用-D選項(xiàng)
ü使用–O2選項(xiàng),完成程序的優(yōu)化工作衫生。為了能夠看出優(yōu)化效果裳瘪,首先在源代碼中添加如圖所示內(nèi)容
圖13優(yōu)化測試代碼
使用命令rm
hello? hello–f,刪除之前生成的文件罪针,使用命令gcc–O2 hello.c–o hello1生成優(yōu)化后的可執(zhí)行文件hello1彭羹,使用命令gcc hello.c–o
hello生成未經(jīng)優(yōu)化的可執(zhí)行文件hello。如圖5-13所示泪酱,將hello1和未優(yōu)化過的可執(zhí)行文件hello進(jìn)行比較派殷。
圖14使用-O2選項(xiàng)
提示:事實(shí)上gcc有四個(gè)優(yōu)化等級(jí)还最,分別對(duì)應(yīng)選項(xiàng)-O0、-O1毡惜、-O2和-O3拓轻,其中-O0代表不優(yōu)化,這個(gè)是缺省值经伙,-O1到-O3優(yōu)化等級(jí)逐步提高扶叉。另外還有個(gè)特殊的優(yōu)化選項(xiàng)-Os,它通常被稱為是優(yōu)化等級(jí)為2.5的優(yōu)化選項(xiàng)帕膜,是在-O2的基礎(chǔ)上對(duì)代碼尺寸進(jìn)行了進(jìn)一步優(yōu)化辜梳。另外,為了更好的驗(yàn)證優(yōu)化的效果泳叠,可以使用time命令作瞄,如time./hello,可以測試當(dāng)前目錄下可執(zhí)行文件hello的執(zhí)行時(shí)間危纫。由于實(shí)驗(yàn)代碼過于簡單宗挥,所以用time測試基本看不出差別,大家可以自己編寫復(fù)雜耗時(shí)的程序用于這個(gè)實(shí)驗(yàn)种蝶。注意:雖然優(yōu)化選項(xiàng)可以加速代碼的運(yùn)行速度契耿,但對(duì)于調(diào)試而言將是一個(gè)很大的挑戰(zhàn)。
因?yàn)榇a在經(jīng)過優(yōu)化之后螃征,原先在源程序中聲明和使用的變量很可能不再使用搪桂,控制流也可能會(huì)突然跳轉(zhuǎn)到意外的地方,循環(huán)語句也有可能因?yàn)檠h(huán)展開而變得到處都有盯滚,所有這些對(duì)調(diào)試來講都將是一場噩夢(mèng)踢械。所以筆者建議在調(diào)試的時(shí)候最好不使用任何優(yōu)化選項(xiàng),只有當(dāng)程序在最終發(fā)行的時(shí)候才考慮對(duì)其進(jìn)行優(yōu)化魄藕。