GCC 編譯c程序的方法及過(guò)程解析
目前 Linux 下最常用的 C 語(yǔ)言編譯器是 GCC ( GNU Compiler Collection ),它是 GNU 項(xiàng)目中符合 ANSI C 標(biāo)準(zhǔn)的編譯系統(tǒng),能夠編譯用 C 、 C++ 和 Object C 等語(yǔ)言編寫的程序。 GCC 不僅功能非常強(qiáng)大,結(jié)構(gòu)也異常靈活。最值得稱道的一點(diǎn)就是它可以通過(guò)不同的前端模塊來(lái)支持各種語(yǔ)言,如Java 、 Fortran 、 Pascal 、 Modula-3 和 Ada 等。開放、自由和靈活是 Linux 的魅力所在,而這一點(diǎn)在 GCC 上的體現(xiàn)就是程序員通過(guò)它能夠更好地控制整個(gè)編譯過(guò)程。在使用 GCC 編譯程序時(shí),編譯過(guò)程可以被細(xì)分為四個(gè)階段:
預(yù)處理( Pre-Processing )
編譯( Compiling )
匯編( Asse mbling )
鏈接( Linking )
Linux 程序員可以根據(jù)自己的需要讓 GCC 在編譯的任何階段結(jié)束,以便檢查或使用編譯器在該階段的輸出信息,或者對(duì)最后生成的二進(jìn)制文件進(jìn)行控制,以便通過(guò)加入不同數(shù)量和種類的調(diào)試代碼來(lái)為今后的調(diào)試做好準(zhǔn)備。和其它常用的編譯器一樣, GCC 也提供了靈活而強(qiáng)大的代碼優(yōu)化功能,利用它可以生成執(zhí)行效率更高的代碼。
GCC 提供了 30 多條警告信息和三個(gè)警告級(jí)別,使用它們有助于增強(qiáng)程序的穩(wěn)定性和可移植性。此外, GCC 還對(duì)標(biāo)準(zhǔn)的 C 和 C++ 語(yǔ)言進(jìn)行了大量的擴(kuò)展,提高程序的執(zhí)行效率,有助于編譯器進(jìn)行代碼優(yōu)化,能夠減輕編程的工作量。
C 程序的編譯過(guò)程主要分為四個(gè)階段:pre-processing,compiling,assembling,linking;
常用文件的后綴名:
gcc 預(yù)處理階段:主要對(duì)包含的頭文件(#include )和宏定義(#define,#ifdef … )進(jìn)行處理??梢允褂谩癵cc -E” 讓gcc 在預(yù)處理之后停止編譯過(guò)程,生成 *.i 文件。
[root@localhost gcc]# gcc -E hello.c -o hello.i
gcc 編譯階段:gcc 首先要檢查代碼的規(guī)范性,是否有語(yǔ)法錯(cuò)誤等。以確定代碼實(shí)際要做的工作,在檢查無(wú)誤后,gcc 把代碼翻譯成匯編語(yǔ)言。用戶可以使用-S 選項(xiàng)進(jìn)行查看,該選項(xiàng)只進(jìn)
行編譯而不進(jìn)行匯編,生成匯編代碼。
[root@localhost gcc]# gcc -S hello.i -o hello.s
gcc 匯編階段:生成目標(biāo)代碼 *.o ;有兩種方式:使用 gcc 直接從源代碼生成目標(biāo)代碼 gcc -c *.s -o *.o 以及使用匯編器從匯編代碼生成目標(biāo)代碼 as *.s -o *.o
[root@localhost gcc]# gcc -c hello.s -o hello.o
[root@localhost gcc]# as hello.s -o hello.o
也可以直接使用as *.s, 將執(zhí)行匯編、鏈接過(guò)程生成可執(zhí)行文件a.out, 可以像上面使用-o 選項(xiàng)指定輸出文件的格式。
gcc 鏈接階段:生成可執(zhí)行文件;可以生成的可執(zhí)行文件格式有: a.out/*/,當(dāng)然可能還有其它格式。
[root@localhost gcc]# gcc hello.o 生成可執(zhí)行文件 a.out
[root@localhost gcc]# gcc hello.o -o hello 生成可執(zhí)行文件 hello
gcc 常用編譯選項(xiàng):
-Dmacro 定義指定的宏,使它能夠通過(guò)源碼中的 #ifdef 進(jìn)行檢驗(yàn);
-O 、 -O2 、 -O3 將優(yōu)化狀態(tài)打開,該選項(xiàng)不能與 -g 選項(xiàng)聯(lián)合使用;
-v 啟動(dòng)所有警報(bào),打印編譯過(guò)程的信息;
-Wall 在發(fā)生警報(bào)時(shí)取消編譯操作,即將警報(bào)看作是錯(cuò)誤;
-Werror 在發(fā)生警報(bào)時(shí)取消編譯操作,即把報(bào)警當(dāng)作是錯(cuò)誤;
-w 禁止所有的報(bào)警。
gcc 鏈接庫(kù)文件的使用
在 linux 下開發(fā)軟件時(shí),完全不使用第三方函數(shù)庫(kù)的情況是比較少見(jiàn)的,通常來(lái)講都需要借助一個(gè)或多個(gè)函數(shù)庫(kù)的支持才能夠完成相應(yīng)的功能。從程序員的角度看,函數(shù)庫(kù)實(shí)際上就是一些頭文件( .h )和庫(kù)文件( .so 或者 .a )的集合。雖然 Linux 下的大多數(shù)函數(shù)都默認(rèn)將頭文件放到/usr/include/ 目錄下,而庫(kù)文件則放到 /usr/lib/ 目錄下,但并不是所有的情況都是這樣。正因如此, GCC 在編譯時(shí)必須有自己的辦法來(lái)查找所需要的頭文件和庫(kù)文件。 GCC 采用搜索目錄的辦法來(lái)查找所需要的文件, -I 選項(xiàng)可以向 GCC 的頭文件搜索路徑中添加新的目錄。例如,如果在/home/justin/include/ 目錄下有編譯時(shí)所需要的頭文件,為了讓 GCC 能夠順利地找到它們,就可以使用 -I 選項(xiàng):
# gcc foo.c -I /home/justin/include -o foo
同樣,如果使用了不在標(biāo)準(zhǔn)位置的庫(kù)文件,那么可以通過(guò) -L 選項(xiàng)向 GCC 的庫(kù)文件搜索路徑中添加新的目錄。例如,如果在 /home/xiaowp/lib/ 目錄下有鏈接時(shí)所需要的庫(kù)文件 libfoo.so ,為了讓 GCC 能夠順利地找到它,可以使用下面的命令:
# gcc foo.c -L /home/justin/lib -lfoo -o foo
值得好好解釋一下的是 -l 選項(xiàng),它指示 GCC 去連接庫(kù)文件 libfoo.so 。
Linux 下的庫(kù)文件在命名時(shí)有一個(gè)約定,那就是應(yīng)該以lib 三個(gè)字母開頭,由于所有的庫(kù)文件都遵循了同樣的規(guī)范,因此在用-l 選項(xiàng)指定鏈接的庫(kù)文件名時(shí)可以省去lib 三個(gè)字母,也就是說(shuō)GCC 在對(duì)-lfoo 進(jìn)行處理時(shí),會(huì)自動(dòng)去鏈接名為libfoo.so
Linux 下的庫(kù)文件分為兩大類分別是動(dòng)態(tài)鏈接庫(kù)(通常以.so 結(jié)尾)和靜態(tài)鏈接庫(kù)(通常以.a 結(jié)尾),兩者的差別僅在程序執(zhí)行時(shí)所需的代碼是在運(yùn)行時(shí)動(dòng)態(tài)加載的,還是在編譯時(shí)靜態(tài)加載的 。默認(rèn)情況下,GCC 在鏈接時(shí)優(yōu)先使用動(dòng)態(tài)鏈接庫(kù),只有當(dāng)動(dòng)態(tài)鏈接庫(kù)不存在時(shí)才考慮使用靜態(tài)鏈接庫(kù),如果需要的話可以在編譯時(shí)加上-static 選項(xiàng),強(qiáng)制使用靜態(tài)鏈接庫(kù)。例如,如果在home/justin/lib/ 目錄下有鏈接時(shí)所需要的庫(kù)文件libfoo.so 和libfoo.a ,為了讓GCC 在鏈接時(shí)只用到靜態(tài)鏈接庫(kù),可以使用下面的命令:
# gcc foo.c -L /home/justin/lib -static -lfoo -o foo 的文件。
對(duì)于動(dòng)態(tài)庫(kù)和靜態(tài)庫(kù)文件的創(chuàng)建方法,此處不作詳細(xì)解釋,可以參考另外一篇linux c 庫(kù)文件創(chuàng)建方法。
上一篇:C經(jīng)典冒泡排序法實(shí)現(xiàn)代碼
欄 目:C語(yǔ)言
下一篇:win32使用openfilename瀏覽文件窗口示例
本文標(biāo)題:GCC 編譯c程序的方法及過(guò)程解析
本文地址:http://mengdiqiu.com.cn/a1/Cyuyan/3793.html
您可能感興趣的文章
- 01-10使用OpenGL實(shí)現(xiàn)3D立體顯示的程序代碼
- 01-10基于C程序啟動(dòng)代碼的深入分析
- 01-10探討:程序在內(nèi)存中的分配(常量,局部變量,全局變量,程序代碼)問(wèn)
- 01-10用C++實(shí)現(xiàn)隊(duì)列的程序代碼
- 01-10C語(yǔ)言程序設(shè)計(jì)50例(經(jīng)典收藏)
- 01-10解析四則表達(dá)式的編譯過(guò)程及生成匯編代碼
- 01-10淺析C語(yǔ)言中的sizeof
- 01-10如何將C語(yǔ)言代碼轉(zhuǎn)換為應(yīng)用程序(也就是編譯)
- 01-10使用VC6.0對(duì)C語(yǔ)言程序進(jìn)行調(diào)試的基本手段分享
- 01-10C語(yǔ)言小程序 楊輝三角示例代碼


閱讀排行
- 1C語(yǔ)言 while語(yǔ)句的用法詳解
- 2java 實(shí)現(xiàn)簡(jiǎn)單圣誕樹的示例代碼(圣誕
- 3利用C語(yǔ)言實(shí)現(xiàn)“百馬百擔(dān)”問(wèn)題方法
- 4C語(yǔ)言中計(jì)算正弦的相關(guān)函數(shù)總結(jié)
- 5c語(yǔ)言計(jì)算三角形面積代碼
- 6什么是 WSH(腳本宿主)的詳細(xì)解釋
- 7C++ 中隨機(jī)函數(shù)random函數(shù)的使用方法
- 8正則表達(dá)式匹配各種特殊字符
- 9C語(yǔ)言十進(jìn)制轉(zhuǎn)二進(jìn)制代碼實(shí)例
- 10C語(yǔ)言查找數(shù)組里數(shù)字重復(fù)次數(shù)的方法
本欄相關(guān)
- 04-02c語(yǔ)言函數(shù)調(diào)用后清空內(nèi)存 c語(yǔ)言調(diào)用
- 04-02func函數(shù)+在C語(yǔ)言 func函數(shù)在c語(yǔ)言中
- 04-02c語(yǔ)言的正則匹配函數(shù) c語(yǔ)言正則表達(dá)
- 04-02c語(yǔ)言用函數(shù)寫分段 用c語(yǔ)言表示分段
- 04-02c語(yǔ)言中對(duì)數(shù)函數(shù)的表達(dá)式 c語(yǔ)言中對(duì)
- 04-02c語(yǔ)言編寫函數(shù)冒泡排序 c語(yǔ)言冒泡排
- 04-02c語(yǔ)言沒(méi)有round函數(shù) round c語(yǔ)言
- 04-02c語(yǔ)言分段函數(shù)怎么求 用c語(yǔ)言求分段
- 04-02C語(yǔ)言中怎么打出三角函數(shù) c語(yǔ)言中怎
- 04-02c語(yǔ)言調(diào)用函數(shù)求fibo C語(yǔ)言調(diào)用函數(shù)求
隨機(jī)閱讀
- 08-05織夢(mèng)dedecms什么時(shí)候用欄目交叉功能?
- 08-05DEDE織夢(mèng)data目錄下的sessions文件夾有什
- 01-10delphi制作wav文件的方法
- 08-05dedecms(織夢(mèng))副欄目數(shù)量限制代碼修改
- 04-02jquery與jsp,用jquery
- 01-11Mac OSX 打開原生自帶讀寫NTFS功能(圖文
- 01-10C#中split用法實(shí)例總結(jié)
- 01-11ajax實(shí)現(xiàn)頁(yè)面的局部加載
- 01-10使用C語(yǔ)言求解撲克牌的順子及n個(gè)骰子
- 01-10SublimeText編譯C開發(fā)環(huán)境設(shè)置