<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>

新聞中心

EEPW首頁(yè) > 嵌入式系統 > GCC使用入門(mén)

GCC使用入門(mén)

——
作者: 時(shí)間:2007-04-17 來(lái)源: 收藏
通常所說(shuō)的GCC是GUN Compiler Collection的簡(jiǎn)稱(chēng),除了編譯程序之外,它還含其他相關(guān)工具,所以它能把易于人類(lèi)使用的高級語(yǔ)言編寫(xiě)的源代碼構建成計算機能夠直接執行的二進(jìn)制代碼。GCC是Linux平臺下最常用的編譯程序,它是Linux平臺的事實(shí)標準。同時(shí),在Linux平臺下的嵌入式開(kāi)發(fā)領(lǐng)域,GCC也是用得最普遍的一種。GCC之所以被廣泛采用,是因為它能支持各種不同的目標體系結構。例如,它既支持基于宿主的開(kāi)發(fā)(簡(jiǎn)單講就是要為某平臺編譯程序,就在該平臺上編譯),也支持交叉編譯(即在A(yíng)平臺上編譯的程序是供平臺B使用的)。目前,GCC支持的體系結構有四十余種,常見(jiàn)的有X86系列、Arm、PowerPC等。同時(shí),GCC還能運行在不同的操作系統上,如Linux、Solaris、Windows等。

除了上面講的之外,GCC除了支持C語(yǔ)言外,還支持多種其他語(yǔ)言,例如C++、Ada、Java、Objective-C、FORTRAN、Pascal等。

本系列文章中,我們不僅介紹GCC的基本功能,還涉及到一些諸如優(yōu)化之類(lèi)的高級功能。另外,我們還考察GCC的一些映像操作工具,如size和objcopy等,這將在后續的文章中加以介紹。

二、程序的編譯過(guò)程

對于GUN來(lái)說(shuō),程序的編譯要經(jīng)歷預處理、編譯、匯編、連接四個(gè)階段,如下圖所示:

     

從功能上分,預處理、編譯、匯編是三個(gè)不同的階段,但GCC的實(shí)際操作上,它可以把這三個(gè)步驟合并為一個(gè)步驟來(lái)執行。下面我們以C語(yǔ)言為例來(lái)談一下不同階段的輸入和輸出情況。

在預處理階段,輸入的是C語(yǔ)言的源文件,通常為*.c。它們通常帶有.h之類(lèi)頭文件的包含文件。這個(gè)階段主要處理源文件中的#ifdef、 #include和#define命令。該階段會(huì )生成一個(gè)中間文件*.i,但實(shí)際工作中通常不用專(zhuān)門(mén)生成這種文件,因為基本上用不到;若非要生成這種文件不可,可以利用下面的示例命令:

gcc -E  test.c -o test.i 


在編譯階段,輸入的是中間文件*.i,編譯后生成匯編語(yǔ)言文件*.s 。這個(gè)階段對應的GCC命令如下所示:

GCC -S test.i -o test.s  


在匯編階段,將輸入的匯編文件*.s轉換成機器語(yǔ)言*.o。這個(gè)階段對應的GCC命令如下所示:

GCC -c test.s -o test.o  


最后,在連接階段將輸入的機器代碼文件*.s(與其它的機器代碼文件和庫文件)匯集成一個(gè)可執行的二進(jìn)制代碼文件。這一步驟,可以利用下面的示例命令完成:

GCC test.o -o test  


上面介紹了GCC編譯過(guò)程的四個(gè)階段以及相應的命令。下面我們進(jìn)一步介紹常用的GCC的模式。

三、GCC常用模式

這里介紹GCC追常用的兩種模式:編譯模式和編譯連接模式。下面以一個(gè)例子來(lái)說(shuō)明各種模式的使用方法。為簡(jiǎn)單起見(jiàn),假設我們全部的源代碼都在一個(gè)文件test.c中,要想把這個(gè)源文件直接編譯成可執行程序,可以使用以下命令:

$ GCC -o test 


這里test.c是源文件,生成的可執行代碼存放在一個(gè)名為test 的文件中(該文件是機器代碼并且可執行)。-o 是生成可執行文件的輸出選項。如果我們只想讓源文件生成目標文件(給文件雖然也是機器代碼但不可執行),可以使用標記-c ,詳細命令如下所示:

$ GCC -c test.c 


默認情況下,生成的目標文件被命名為test.o,但我們也可以為輸出文件指定名稱(chēng),如下所示:

$ GCC -c test.c -o  


上面這條命令將編譯后的目標文件命名為mytest.o,而不是默認的test.o。

迄今為止,我們談?wù)摰某绦騼H涉及到一個(gè)源文件;現實(shí)中,一個(gè)程序的源代碼通常包含在多個(gè)源文件之中,這該怎么辦?沒(méi)關(guān)系,即使這樣,用GCC處理起來(lái)也并不復雜,見(jiàn)下例:

$ GCC -o test  first.c second.c third.c 


該命令將同時(shí)編譯三個(gè)源文件,即first.c、second.c和 third.c,然后將它們連接成一個(gè)可執行程序,名為test。

需要注意的是,要生成可執行程序時(shí),一個(gè)程序無(wú)論有有一個(gè)源文件還是多個(gè)源文件,所有被編譯和連接的源文件中必須有且僅有一個(gè)main函數,因為main函數是該程序的入口點(diǎn)(換句話(huà)說(shuō),當系統調用該程序時(shí),首先將控制權授予程序的main函數)。但如果僅僅是把源文件編譯成目標文件的時(shí)候,因為不會(huì )進(jìn)行連接,所以main函數不是必需的。

四、常用選項

許多情況下,頭文件和源文件會(huì )單獨存放在不同的目錄中。例如,假設存放源文件的子目錄名為./src,而包含文件則放在層次的其他目錄下,如./inc。當我們在./src 目錄下進(jìn)行編譯工作時(shí),如何告訴GCC到哪里找頭文件呢?方法如下所示:

$ gcc test.c –I../inc -o test 


上面的命令告訴GCC包含文件存放在./inc 目錄下,在當前目錄的上一級。如果在編譯時(shí)需要的包含文件存放在多個(gè)目錄下,可以使用多個(gè)-I 來(lái)指定各個(gè)目錄:

$ gcc test.c –I../inc –I../../inc2 -o test 


這里指出了另一個(gè)包含子目錄inc2,較之前目錄它還要在再上兩級才能找到。

另外,我們還可以在編譯命令行中定義符號常量。為此,我們可以簡(jiǎn)單的在命令行中使用-D選項即可,如下例所示:

$ gcc -DTEST_CONFIGURATION test.c -o test 


上面的命令與在源文件中加入下列命令是等效的:

#define TEST_CONFIGURATION 


在編譯命令行中定義符號常量的好處是,不必修改源文件就能改變由符號常量控制的行為。

五、警告功能

當GCC在編譯過(guò)程中檢查出錯誤的話(huà),它就會(huì )中止編譯;但檢測到警告時(shí)卻能繼續編譯生成可執行程序,因為警告只是針對程序結構的診斷信息,它不能說(shuō)明程序一定有錯誤,而是存在風(fēng)險,或者可能存在錯誤。雖然GCC提供了非常豐富的警告,但前提是你已經(jīng)啟用了它們,否則它不會(huì )報告這些檢測到的警告。

在眾多的警告選項之中,最常用的就是-Wall選項。該選項能發(fā)現程序中一系列的常見(jiàn)錯誤警告,該選項用法舉例如下:

$ gcc -Wall test.c -o test 


該選項相當于同時(shí)使用了下列所有的選項:

◆unused-function:遇到僅聲明過(guò)但尚未定義的靜態(tài)函數時(shí)發(fā)出警告。

◆unused-label:遇到聲明過(guò)但不使用的標號的警告。

◆unused-parameter:從未用過(guò)的函數參數的警告。

◆unused-variable:在本地聲明但從未用過(guò)的變量的警告。

◆unused-value:僅計算但從未用過(guò)的值得警告。

◆Format:檢查對printf和scanf等函數的調用,確認各個(gè)參數類(lèi)型和格式串中的一致。

◆implicit-int:警告沒(méi)有規定類(lèi)型的聲明。

◆implicit-function-:在函數在未經(jīng)聲明就使用時(shí)給予警告。

◆char-subscripts:警告把char類(lèi)型作為數組下標。這是常見(jiàn)錯誤,程序員經(jīng)常忘記在某些機器上char有符號。

◆missing-braces:聚合初始化兩邊缺少大括號。

◆Parentheses:在某些情況下如果忽略了括號,編譯器就發(fā)出警告。

◆return-type:如果函數定義了返回類(lèi)型,而默認類(lèi)型是int型,編譯器就發(fā)出警告。同時(shí)警告那些不帶返回值的 return語(yǔ)句,如果他們所屬的函數并非void類(lèi)型。

◆sequence-point:出現可疑的代碼元素時(shí),發(fā)出報警。

◆Switch:如果某條switch語(yǔ)句的參數屬于枚舉類(lèi)型,但是沒(méi)有對應的case語(yǔ)句使用枚舉元素,編譯器就發(fā)出警告(在switch語(yǔ)句中使用default分支能夠防止這個(gè)警告)。超出枚舉范圍的case語(yǔ)句同樣會(huì )導致這個(gè)警告。

◆strict-aliasing:對變量別名進(jìn)行最嚴格的檢查。

◆unknown-pragmas:使用了不允許的#pragma。

◆Uninitialized:在初始化之前就使用自動(dòng)變量。

需要注意的是,各警告選項既然能使之生效,當然也能使之關(guān)閉。比如假設我們想要使用-Wall來(lái)啟用個(gè)選項,同時(shí)又要關(guān)閉unused警告,利益通過(guò)下面的命令來(lái)達到目的:

$ gcc -Wall -Wno-unused test.c -o test 


下面是使用-Wall選項的時(shí)候沒(méi)有生效的一些警告項:

◆cast-align:一旦某個(gè)指針類(lèi)型強制轉換時(shí),會(huì )導致目標所需的地址對齊邊界擴展,編譯器就發(fā)出警告。例如,某些機器上只能在2或4字節邊界上訪(fǎng)問(wèn)整數,如果在這種機型上把char *強制轉換成int *類(lèi)型, 編譯器就發(fā)出警告。

◆sign-compare:將有符號類(lèi)型和無(wú)符號類(lèi)型數據進(jìn)行比較時(shí)發(fā)出警告。

◆missing-prototypes :如果沒(méi)有預先聲明函數原形就定義了全局函數,編譯器就發(fā)出警告。即使函數定義自身提供了函數原形也會(huì )產(chǎn)生這個(gè)警告。這樣做的目的是檢查沒(méi)有在頭文件中聲明的全局函數。

◆Packed:當結構體帶有packed屬性但實(shí)際并沒(méi)有出現緊縮式給出警告。

◆Padded:如果結構體通過(guò)充填進(jìn)行對齊則給出警告。

◆unreachable-code:如果發(fā)現從未執行的代碼時(shí)給出警告。

◆Inline:如果某函數不能內嵌(inline),無(wú)論是聲明為inline或者是指定了-finline-functions 選項,編譯器都將發(fā)出警告。 

◆disabled-optimization:當需要太長(cháng)時(shí)間或過(guò)多資源而導致不能完成某項優(yōu)化時(shí)給出警告。

上面是使用-Wall選項時(shí)沒(méi)有生效,但又比較常用的一些警告選項。本文中要介紹的最后一個(gè)常用警告選項是-Werror。使用該選項后,GCC發(fā)現可疑之處時(shí)不會(huì )簡(jiǎn)單的發(fā)出警告就算完事,而是將警告作為一個(gè)錯誤而中斷編譯過(guò)程。該選項在希望得到高質(zhì)量代碼時(shí)非常有用。 

六、小結

本文介紹了GCC的基本編譯過(guò)程和編譯模式,并詳細闡述了GCC的一些常用選項以及警告功能。這些是在利用GCC進(jìn)行應用編程時(shí)最基本也最常用的一些內容,我們會(huì )在后續文章中繼續介紹GCC的調試和優(yōu)化技術(shù)。



評論


相關(guān)推薦

技術(shù)專(zhuān)區

關(guān)閉
国产精品自在自线亚洲|国产精品无圣光一区二区|国产日产欧洲无码视频|久久久一本精品99久久K精品66|欧美人与动牲交片免费播放
<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>