GCC編譯器總結(jié)

GCC簡介

1、GCC經(jīng)過那么多年的發(fā)展斑胜,已經(jīng)從最初的C編譯器轉(zhuǎn)變成了編譯器的集合控淡,官方定義是GNU Complier Collection,現(xiàn)在的GCC不僅支持C還支持C++止潘、Java等語言掺炭。
2、GCC是一個(gè)編譯系統(tǒng)的驅(qū)動程序覆山,負(fù)責(zé)解析輸入的參數(shù)竹伸,依次調(diào)用預(yù)處理器(cpp)泥栖、編譯器(ccl/cclplus)簇宽、匯編器(as)勋篓、鏈接器(ld)生成可執(zhí)行文件。
3魏割、GCC 和 G++ 的區(qū)別并不是前者用來編譯C代碼譬嚣,后者用來編譯 C++ 代碼。它們的區(qū)別是GCC把后綴為c的文件當(dāng)C代碼處理(ccl編譯)钞它,而 G++ 則當(dāng)作 C++ 處理(cclplus編譯)拜银,對于后綴為cpp的文件gcc和 g++ 處理過程沒有什么區(qū)別。GCC默認(rèn)是不能編譯 C++ 程序的遭垛,需要加上-lstdc++選項(xiàng)尼桶,G++ 是可以直接編譯的,G++相當(dāng)于是對GCC的封裝锯仪。

GCC編譯過程

在介紹GCC編譯步驟之前泵督,首先需要了解GCC支持的后綴文件類型。

后綴名 對應(yīng)語言
.c C程序
.C/.cc/.cxx C++程序
.i 預(yù)處理后的C程序
.ii 預(yù)處理后的C++程序
.s/.S 匯編語言程序
.h 頭文件
.o 目標(biāo)文件
.a/.so 編譯后的庫文件

GCC編譯流程分為四個(gè)步驟:預(yù)處理(生成.i/.ii文件)庶喜、編譯(生成.s/.S文件)小腊、匯編(生成.o文件)、鏈接(生成可執(zhí)行文件)久窟。


gcc指令的一般格式為:
gcc [選項(xiàng)] 要編譯的文件 [選項(xiàng)] [目標(biāo)文件]
其中秩冈,目標(biāo)文件可缺省,gcc默認(rèn)生成可執(zhí)行的文件為a.out


#include <stdio.h>
int main()
{
    printf("Hello World\n");
    return 0;
}

1斥扛、預(yù)處理
對于該階段入问,gcc將stdio.h文件中的代碼包含進(jìn)這段程序,我們可以利用gcc -E test.c -o test.i命令來生成預(yù)處理過的.i文件犹赖。-E選項(xiàng)代表讓gcc在預(yù)處理階段后停止編譯队他。test.i文件中的內(nèi)容如下所示,可以看出stdio.h文件中的內(nèi)容被展開峻村。

extern int fprintf (FILE *__restrict __stream,
  __const char *__restrict __format, ...);
  ......
  # 8 "test.c" 2
int main()
{
    printf("Hello World\n");
    return 0;
}

2麸折、編譯
該階段主要是對預(yù)編譯后的.i文件編譯,生成匯編代碼的.s文件粘昨。gcc首先要檢查代碼的規(guī)范性垢啼、是否有語法錯(cuò)誤等,以確定代碼的實(shí)際要做的工作张肾,在檢查無誤后芭析,gcc把代碼翻譯成匯編語言。我們可以使用-S選項(xiàng)來進(jìn)行查看吞瞪,該選項(xiàng)只進(jìn)行編譯而不進(jìn)行匯編過程馁启,生成匯編代碼。
我們可以利用gcc -S test.i -o test.s命令進(jìn)行編譯過程。test.s文件中的內(nèi)容如下所示惯疙。

    .file   "test.c"
    .section    .rodata
.LC0:
    .string "Hello World"
    .text
.globl main
    .type   main, @function
main:
    pushl   %ebp
    movl    %esp, %ebp
    andl    $-16, %esp
    subl    $16, %esp
    movl    $.LC0, (%esp)
    call    puts
    movl    $0, %eax
    leave
    ret
    .size   main, .-main
    .ident  "GCC: (GNU) 4.4.7 20120313 (Red Hat 4.4.7-16)"
    .section    .note.GNU-stack,"",@progbits

3翠勉、匯編
該階段是將編譯后的.s文件轉(zhuǎn)化成二進(jìn)制文件.o的過程,利用-c選項(xiàng)就可以生成二進(jìn)制.o文件霉颠。我們可以利用gcc -c test.s -o test.o生成二進(jìn)制代碼对碌。
4、鏈接


該階段主要將成功編譯的二進(jìn)制文件進(jìn)行鏈接操作蒿偎,生成可執(zhí)行文件朽们。利用gcc test.o -o test生成可執(zhí)行文件test,運(yùn)行./test即可打印出hello world诉位。


總結(jié)一下:

gcc -E  test.c -o test.i    //把原代碼交給cpp預(yù)處理器生成經(jīng)過預(yù)處理后的中間文件test.i
gcc -S test.i -o test.s     //把經(jīng)過預(yù)處理之后的test.i文件交給編譯器cc1生成test.s文件
gcc -c test.s -o test.o     //把經(jīng)過編譯后匯編文件test.s交給as進(jìn)行匯編骑脱,生成目標(biāo)test.o文件
gcc test.o -o test          //將as匯編之后的目標(biāo)文件交給ld鏈接成一個(gè)可執(zhí)行的文件test

GCC常用編譯選項(xiàng)

1、總體編譯選項(xiàng)

選項(xiàng)名稱 作用
-c 只是編譯不鏈接苍糠,生成目標(biāo)文件.o
-S 只是編譯不匯編惜姐,生成匯編代碼
-E 只進(jìn)行預(yù)編譯榕订,不做其他處理
-g 在可執(zhí)行程序中包含標(biāo)準(zhǔn)調(diào)試信息
-o file 把輸出文件輸出到file里
-v 打印出編譯器內(nèi)部編譯各過程的命令行信息和編譯器的版本
-I dir 在頭文件的搜索路徑列表中添加dir目錄
-L dir 在庫文件的搜索路徑列表中添加dir目錄
-static 鏈接靜態(tài)庫
-llibrary 連接名為library的庫文件

表中前邊幾個(gè)選項(xiàng)在GCC編譯步驟中已經(jīng)有所了解炫加,主要對表中后四個(gè)選項(xiàng)進(jìn)行介紹。
當(dāng)我們進(jìn)行程序開發(fā)時(shí)靶瘸,基本都會用到很多函數(shù)庫寝优,從程序員的角度看条舔,函數(shù)庫就是封裝的一些頭文件(.h)和庫文件(.a/.so),Linux系統(tǒng)下頭文件一般默認(rèn)放到/usr/include/目錄下乏矾,庫文件放在/usr/lib/目錄下孟抗,如果我們使用的庫不在標(biāo)準(zhǔn)路徑下,我們就需要指定頭文件和庫文件的路徑以便讓gcc找到它們钻心。
舉個(gè)例子凄硼,假設(shè)上一節(jié)test.c主要實(shí)現(xiàn)C語言連接mysql數(shù)據(jù)庫的功能,我們從官網(wǎng)下載的mysql connectors的頭文件在/usr/local/mysq/include/路徑下捷沸,庫函數(shù)在/usr/local/mysql/lib/路徑下摊沉。
我們可以利用

gcc -c -I /usr/local/mysql/include test.c -o test.o

生成test.o二進(jìn)制文件,再利用

gcc -L /usr/local/mysql/lib -lmysqlclient test.o -o test

進(jìn)行鏈接操作產(chǎn)生可執(zhí)行的test文件痒给。這兩步也可以合成一步说墨,直接生成可執(zhí)行的test文件

gcc -I /usr/local/mysql/include -L /usr/local/mysql/lib -lmysqlclient test.c -o test

Linux下的庫文件分為兩大類分別是動態(tài)鏈接庫(通常以.so結(jié)尾)和靜態(tài)鏈接庫(通常以.a結(jié)尾),二者的區(qū)別僅在于程序執(zhí)行時(shí)所需的代碼是在運(yùn)行時(shí)動態(tài)加載的苍柏,還是在編譯時(shí)靜態(tài)加載的尼斧。
默認(rèn)情況下, GCC在鏈接時(shí)優(yōu)先使用動態(tài)鏈接庫试吁,只有當(dāng)動態(tài)鏈接庫不存在時(shí)才考慮使用靜態(tài)鏈接庫棺棵,如果需要使用靜態(tài)鏈接庫可以在編譯時(shí)加上-static選項(xiàng),強(qiáng)制使用靜態(tài)鏈接庫。
比如在/usr/local/mysql/lib目錄下有鏈接時(shí)所需要的庫文件libmysqlclient.so和libmysqlclient.a烛恤,為了讓GCC在鏈接時(shí)只用到靜態(tài)鏈接庫爬橡,可以使用下面的命令:
gcc –L /usr/local/mysql/lib -static –lmysqlclient test.o –o test

需要注意的是:

  • -I dir-L dir都只是指定了路徑,而沒有指定文件棒动,因此不能在路徑中包含文件名。
  • 另外值得詳細(xì)解釋一下的是-l選項(xiàng)宾添, 它指示gcc去連接庫文件libXXX.so船惨。由于在Linux下的庫文件命名時(shí)有一個(gè)規(guī)定:必須以lib三個(gè)字母開頭。因此在用-l選項(xiàng)指定鏈接的庫文件名時(shí)可以省去lib三個(gè)字母缕陕。也就是說gcc在對”-lXXX”進(jìn)行處理時(shí)粱锐,會自動去鏈接名為libXXX.so的文件。

2扛邑、其他常用編譯選項(xiàng)

選項(xiàng)名稱 作用
-ansi 支持符合ANSI標(biāo)準(zhǔn)的C程序
-pedantic 允許發(fā)出ANSI C標(biāo)準(zhǔn)所列的全部警告信息
-pedantic-error 允許發(fā)出ANSI C標(biāo)準(zhǔn)所列的全部錯(cuò)誤信息
-Wall 允許發(fā)出gcc提供的所有有用的報(bào)警信息
-Werror 把所有的告警信息轉(zhuǎn)化為錯(cuò)誤信息怜浅,并在告警發(fā)生時(shí)終止編譯過程
-O 主要進(jìn)行線程跳轉(zhuǎn)(Thread Jump)和延遲退棧(Deferred Stack Pops)兩種優(yōu)化
-O2 除了完成所有“-O1”級別的優(yōu)化之外,同時(shí)還要進(jìn)行一些額外的調(diào)整工作蔬崩,如處理器指令調(diào)度等
-O3 還包括循環(huán)展開和其他一些與處理器特性相關(guān)的優(yōu)化工作
-static 指示鏈接器構(gòu)建一個(gè)完全鏈接的可執(zhí)行程序恶座,即鏈接靜態(tài)庫而不鏈接動態(tài)庫
-fPIC 指示鏈接器創(chuàng)建一個(gè)共享的目標(biāo)文件,即so文件
-shared 生成動態(tài)庫沥阳,一般和上面的-fPIC一起使用

參考文獻(xiàn):


GCC學(xué)習(xí)總結(jié)

Linux GCC常用命令

GCC 編譯詳解

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末跨琳,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子桐罕,更是在濱河造成了極大的恐慌脉让,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,372評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件功炮,死亡現(xiàn)場離奇詭異溅潜,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)薪伏,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評論 3 392
  • 文/潘曉璐 我一進(jìn)店門滚澜,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人嫁怀,你說我怎么就攤上這事博秫。” “怎么了眶掌?”我有些...
    開封第一講書人閱讀 162,415評論 0 353
  • 文/不壞的土叔 我叫張陵挡育,是天一觀的道長。 經(jīng)常有香客問我朴爬,道長即寒,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,157評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮母赵,結(jié)果婚禮上逸爵,老公的妹妹穿的比我還像新娘。我一直安慰自己凹嘲,他們只是感情好师倔,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,171評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著周蹭,像睡著了一般趋艘。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上凶朗,一...
    開封第一講書人閱讀 51,125評論 1 297
  • 那天瓷胧,我揣著相機(jī)與錄音,去河邊找鬼棚愤。 笑死搓萧,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的宛畦。 我是一名探鬼主播瘸洛,決...
    沈念sama閱讀 40,028評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼次和!你這毒婦竟也來了货矮?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,887評論 0 274
  • 序言:老撾萬榮一對情侶失蹤斯够,失蹤者是張志新(化名)和其女友劉穎囚玫,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體读规,經(jīng)...
    沈念sama閱讀 45,310評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡抓督,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,533評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了束亏。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片铃在。...
    茶點(diǎn)故事閱讀 39,690評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖碍遍,靈堂內(nèi)的尸體忽然破棺而出定铜,到底是詐尸還是另有隱情,我是刑警寧澤怕敬,帶...
    沈念sama閱讀 35,411評論 5 343
  • 正文 年R本政府宣布揣炕,位于F島的核電站,受9級特大地震影響东跪,放射性物質(zhì)發(fā)生泄漏畸陡。R本人自食惡果不足惜鹰溜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,004評論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望丁恭。 院中可真熱鬧曹动,春花似錦、人聲如沸牲览。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽第献。三九已至贡必,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間痊硕,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評論 1 268
  • 我被黑心中介騙來泰國打工押框, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留岔绸,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,693評論 2 368
  • 正文 我出身青樓橡伞,卻偏偏與公主長得像盒揉,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子兑徘,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,577評論 2 353

推薦閱讀更多精彩內(nèi)容