龍華做棋牌網(wǎng)站建設(shè)網(wǎng)站收錄服務(wù)
目錄
0.程序?qū)崿F(xiàn)的兩大環(huán)境
1.gcc如何完成
預(yù)處理
編譯
匯編
鏈接
2.動(dòng)態(tài)庫(kù)與靜態(tài)庫(kù)
對(duì)比二者生成的文件大小
3. gcc常用選項(xiàng)
0.程序?qū)崿F(xiàn)的兩大環(huán)境
任何一個(gè)C程序的實(shí)現(xiàn)都要經(jīng)過(guò)翻譯環(huán)境與執(zhí)行環(huán)境。
在翻譯環(huán)境中又分為4個(gè)部分,預(yù)編譯、編譯、匯編與鏈接。在各個(gè)階段主要完成的任務(wù)有:
1.預(yù)編譯(預(yù)處理):頭文件的包含、注釋的刪除、#define符號(hào)的替換;
2.編譯:將C語(yǔ)言代碼轉(zhuǎn)化為匯編代碼;
3.匯編:把匯編指令轉(zhuǎn)化為二進(jìn)制指令;
4.鏈接:合并符號(hào)表和段表,生成可執(zhí)行程序。
更多詳細(xì)關(guān)于程序?qū)崿F(xiàn)的兩大環(huán)境的知識(shí)請(qǐng)參考:程序?qū)崿F(xiàn)的兩大環(huán)境?。
1.gcc如何完成
通過(guò)gcc指令的不同選項(xiàng)可查看各階段所形成的文件;
格式:gcc? [選項(xiàng)] [目標(biāo)文件名] -o [生成文件名]。
首先在Test.c文件中寫好C代碼:
//Test.c
#include<stdio.h>#define N 100//這是一段注釋.....int main()
{int n = 0;printf("Hello World\n");printf("%d\n", n + N);return 0;
}
預(yù)處理
查看 Test.c 預(yù)處理后的結(jié)果,-E選項(xiàng)的作用是讓 gcc 在預(yù)處理結(jié)束后停止編譯過(guò)程;-o 的作用是將預(yù)處理后的內(nèi)容保存到 test.i 文件中。
gcc -E Test.c -o test.i
?如圖所示,預(yù)處理階段進(jìn)行了頭文件包含、注釋的刪除、#define的替換。
編譯
接下來(lái)將剛剛生成的 test.i 進(jìn)行編譯,并在編譯之后停下來(lái),將結(jié)果寫入 test.s 中。gcc所用選項(xiàng)為 -S。
gcc -S test.i -o test.s
我們雖然可能沒(méi)學(xué)習(xí)過(guò)匯編語(yǔ)言,但依舊隱約認(rèn)識(shí)到這些就是匯編代碼;可見(jiàn)編譯階段就是將C代碼翻譯為匯編指令。?
匯編
gcc所用選項(xiàng)為 -c;-o 將結(jié)果寫入到 test.o 中。
gcc -c test.s -o test.o
正如我們所見(jiàn),匯編完成之后都這這樣的亂碼。其實(shí)匯編之后,生成的文件為二進(jìn)制文件,是用來(lái)給計(jì)算機(jī)看的,咱們已經(jīng)看不懂了。
鏈接
編譯完成之后就進(jìn)入了鏈接階段,鏈接完成之后就會(huì)生成可執(zhí)程序 Test了。
gcc test.o -o Test
但是關(guān)于鏈接,我們需要知道它在鏈接什么。
我們是否好奇過(guò)為什么我們明明沒(méi)有定義過(guò)函數(shù) printf 、return .....等等的函數(shù),但卻可以使用它的功能?
其實(shí),系統(tǒng)把這些函數(shù)的實(shí)現(xiàn)都被做到名為 libc.so.6 的庫(kù)文件中去了,在沒(méi)有特別指定時(shí),gcc 會(huì)到系統(tǒng)默認(rèn)的搜索路徑“/usr/lib”下進(jìn)行查找,也就是鏈接到 libc.so.6 庫(kù)函數(shù)中去,這樣就能實(shí)現(xiàn)函 數(shù) printf 了,而這也就是鏈接的作用。
2.動(dòng)態(tài)庫(kù)與靜態(tài)庫(kù)
函數(shù)庫(kù)一般分為動(dòng)、靜態(tài)庫(kù)兩種。二者的區(qū)別可以理解為私有與公共的區(qū)別。就好比我們需要讀一本《C和指針》,有兩種方法可以選。一種是自己買一本,只有自己可以用,用起來(lái)還挺方便,缺點(diǎn)就是得花錢;第二種是去圖書館借書,圖書館的資源被所有人共享。
gcc 進(jìn)行函數(shù)庫(kù)的鏈接時(shí)可選擇靜態(tài)鏈接或者動(dòng)態(tài)鏈接。
靜態(tài)鏈接就類似于自己買書看,只給自己看同時(shí)還費(fèi)錢(浪費(fèi)內(nèi)存),靜態(tài)鏈接時(shí)會(huì)將庫(kù)文件的代碼全部加入到可執(zhí)行文件中,因此生成的文件比較大。
動(dòng)態(tài)鏈接類似于去圖書館借書。函數(shù)庫(kù)就放在某個(gè)固定的地方,哪個(gè)程序想去使用就去自己去加載它。
Linux下gcc默認(rèn)使用動(dòng)態(tài)鏈接。
對(duì)比二者生成的文件大小
//采用靜態(tài)鏈接
gcc -static Test.c -o Test_static
//默認(rèn)采用動(dòng)態(tài)鏈接
gcc Test.c -o Test
若在靜態(tài)鏈接時(shí)出錯(cuò),可能是因?yàn)槟愕?Linux 沒(méi)有安裝C語(yǔ)言的靜態(tài)庫(kù),須手動(dòng)安裝。?
//安裝C語(yǔ)言靜態(tài)庫(kù)
yum install -y glibc-static
兩種連接方式生成的文件大小幾乎相差百倍。?
3. gcc常用選項(xiàng)
以下是gcc編譯器常用選項(xiàng)匯總
-E 只激活預(yù)處理,這個(gè)不生成文件,你需要把它重定向到一個(gè)輸出文件里面;
-S?編譯到匯編語(yǔ)言不進(jìn)行匯編和鏈接;
-c?編譯到目標(biāo)代碼;
-o 文件輸出到 文件;
-static 此選項(xiàng)對(duì)生成的文件采用靜態(tài)鏈接;
-g?生成調(diào)試信息。GNU 調(diào)試器可利用該信息;
-shared?此選項(xiàng)將盡量使用動(dòng)態(tài)庫(kù),所以生成文件比較小,但是需要系統(tǒng)由動(dòng)態(tài)庫(kù).;
-O0
-O1
-O2
-O3 編譯器的優(yōu)化選項(xiàng)的4個(gè)級(jí)別,-O0表示沒(méi)有優(yōu)化,-O1為缺省值,-O3優(yōu)化級(jí)別最高;
-w?不生成任何警告信息;
-Wall 生成所有警告信息。