新聞中心

EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > Linux下C編程基礎(chǔ)之:gcc編譯器

Linux下C編程基礎(chǔ)之:gcc編譯器

作者: 時(shí)間:2013-09-13 來源:網(wǎng)絡(luò) 收藏

本文引用地址:http://butianyuan.cn/article/257151.htm

(4)鏈接階段。

在成功編譯之后,就進(jìn)入了鏈接階段。這里涉及一個(gè)重要的概念:。

讀者可以重新查看這個(gè)小程序,在這個(gè)程序中并沒有定義“printf”的函數(shù)實(shí)現(xiàn),且在預(yù)編譯中包含進(jìn)的“stdio.h”中也只有該函數(shù)的聲明,而沒有定義函數(shù)的實(shí)現(xiàn),那么,是在哪里實(shí)現(xiàn)“printf”函數(shù)的呢?最后的答案是:系統(tǒng)把這些函數(shù)的實(shí)現(xiàn)都放到名為libc.so.6的庫文件中去了,在沒有特別指定時(shí),gcc會(huì)到系統(tǒng)默認(rèn)的搜索路徑“/usr/lib”下進(jìn)行查找,也就是鏈接到libc.so.6中去,這樣就能調(diào)用函數(shù)“printf”了,而這也正是鏈接的作用。

有靜態(tài)庫和動(dòng)態(tài)庫兩種。靜態(tài)庫是指編譯鏈接時(shí),將庫文件的代碼全部加入可執(zhí)行文件中,因此生成的文件比較大,但在運(yùn)行時(shí)也就不再需要庫文件了。其后綴名通常為“.a”。動(dòng)態(tài)庫與之相反,在編譯鏈接時(shí)并沒有將庫文件的代碼加入可執(zhí)行文件中,而是在程序執(zhí)行時(shí)加載庫,這樣可以節(jié)省系統(tǒng)的開銷。一般動(dòng)態(tài)庫的后綴名為“.so”,如前面所述的libc.so.6就是動(dòng)態(tài)庫。gcc在編譯時(shí)默認(rèn)使用動(dòng)態(tài)庫。

完成了鏈接之后,gcc就可以生成可執(zhí)行文件,如下所示。

[root@localhostgcc]#gcchello.o–ohello

運(yùn)行該可執(zhí)行文件,出現(xiàn)的正確結(jié)果如下。

[root@localhostgcc]#./hello

Hello!Thisisourembeddedworld!

3.3.2gcc編譯選項(xiàng)分析

gcc有超過100個(gè)可用選項(xiàng),主要包括總體選項(xiàng)、告警和出錯(cuò)選項(xiàng)、優(yōu)化選項(xiàng)和體系結(jié)構(gòu)相關(guān)選項(xiàng)。以下對每一類中最常用的選項(xiàng)進(jìn)行講解。

(1)常用選項(xiàng)。

gcc的常用選項(xiàng)如表3.7所示,很多在前面的示例中已經(jīng)有所涉及。

表3.7 gcc常用選項(xiàng)列表

選項(xiàng)

含義

-c

只編譯不鏈接,生成目標(biāo)文件“.o”

-S

只編譯不匯編,生成匯編代碼

-E

只進(jìn)行預(yù)編譯,不做其他處理

-g

在可執(zhí)行程序中包含標(biāo)準(zhǔn)調(diào)試信息

-ofile

將file文件指定為輸出文件

-v

打印出編譯器內(nèi)部編譯各過程的命令行信息和編譯器的版本

-Idir

在頭文件的搜索路徑列表中添加dir目錄

前一小節(jié)已經(jīng)講解了“-c”、“-E”、“-o”、“-S”選項(xiàng)的使用方法,在此主要講解另外2個(gè)非常常用的庫依賴選項(xiàng)“-Idir”。

n “-Idir”

正如上表中所述,“-Idir”選項(xiàng)可以在頭文件的搜索路徑列表中添加dir目錄。由于中頭文件都默認(rèn)放到了“/usr/include/”目錄下,因此,當(dāng)用戶希望添加放置在其他位置的頭文件時(shí),就可以通過“-Idir”選項(xiàng)來指定,這樣,gcc就會(huì)到相應(yīng)的位置查找對應(yīng)的目錄。

比如在“/root/workplace/gcc”下有兩個(gè)文件:

/*hello1.c*/

#includemy.h>

intmain()

{

printf(Hello!!n);

return0;

}

/*my.h*/

#includestdio.h>

這樣,就可在gcc命令行中加入“-I”選項(xiàng):

[root@localhostgcc]gcchello1.c–I/root/workplace/gcc/-ohello1

這樣,gcc就能夠執(zhí)行出正確結(jié)果。

小知識

在include語句中,“>”表示在標(biāo)準(zhǔn)路徑中搜索頭文件,““””表示在本目錄中搜索。故在上例中,可把hello1.c的“#includemy.h>”改為“#include“my.h””,就不需要加上“-I”選項(xiàng)了。

(2)庫選項(xiàng)。

gcc庫選項(xiàng)如表3.8所示。

表3.8 gcc庫選項(xiàng)列表

選項(xiàng)

含義

-static

進(jìn)行靜態(tài)編譯,即鏈接靜態(tài)庫,禁止使用動(dòng)態(tài)庫

-shared

1.可以生成動(dòng)態(tài)庫文件

2.進(jìn)行動(dòng)態(tài)編譯,盡可能地鏈接動(dòng)態(tài)庫,只有當(dāng)沒有動(dòng)態(tài)庫時(shí)才會(huì)鏈接同名的靜態(tài)庫(默認(rèn)選項(xiàng),即可省略)

-Ldir

在庫文件的搜索路徑列表中添加dir目錄

-lname

鏈接稱為libname.a(靜態(tài)庫)或者libname.so(動(dòng)態(tài)庫)的庫文件。若兩個(gè)庫都存在,則根據(jù)編譯方式(-static還是-shared)而進(jìn)行鏈接

-fPIC(或-fpic)

生成使用相對地址的位置無關(guān)的目標(biāo)代碼(PositionIndependentCode)。然后通常使用gcc的-static選項(xiàng)從該P(yáng)IC目標(biāo)文件生成動(dòng)態(tài)庫文件

我們通常需要將一些常用的公共函數(shù)編譯并集成到二進(jìn)制文件(的ELF格式文件),以便其他程序可重復(fù)地使用該文件中的函數(shù),此時(shí)將這種文件叫做函數(shù)庫,使用函數(shù)庫不僅能夠節(jié)省很多內(nèi)存和存儲(chǔ)器的空間資源,而且更重要的是大大降低開發(fā)難度和開銷,提高開發(fā)效率并增強(qiáng)程序的結(jié)構(gòu)性。實(shí)際上,在中的每個(gè)程序都會(huì)鏈接到一個(gè)或者多個(gè)庫。比如使用C函數(shù)的程序會(huì)鏈接到C運(yùn)行時(shí)庫,Qt應(yīng)用程序會(huì)鏈接到Qt支持的相關(guān)圖形庫等。

函數(shù)庫有靜態(tài)庫和動(dòng)態(tài)庫兩種,靜態(tài)庫是一系列的目標(biāo)文件(.o文件)的歸檔文件(文件名格式為libname.a),如果在編譯某個(gè)程序時(shí)鏈接靜態(tài)庫,則鏈接器將會(huì)搜索靜態(tài)庫,從中提取出它所需要的目標(biāo)文件并直接復(fù)制到該程序的可執(zhí)行二進(jìn)制文件(ELF格式文件)之中;動(dòng)態(tài)庫(文件名格式為libname.so[.主版本號.次版本號.發(fā)行號])在程序編譯時(shí)并不會(huì)被鏈接到目標(biāo)代碼中,而是在程序運(yùn)行時(shí)才被載入。

下面舉一個(gè)簡單的例子,講解如何怎么創(chuàng)建和使用這兩種函數(shù)庫。

首先創(chuàng)建unsgn_pow.c文件,它包含unsgn_pow()函數(shù)的定義,具體代碼如下所示。

/*unsgn_pow.c:庫程序*/

unsignedlonglongunsgn_pow(unsignedintx,unsignedinty)

{

unsignedlonglongres=1;

if(y==0)

{

res=1;

}

elseif(y==1)

{

res=x;

}

else

{

res=x*unsgn_pow(x,y-1);

}

returnres;

}

然后創(chuàng)建pow_test.c文件,它會(huì)調(diào)用unsgn_pow()函數(shù)。

/*pow_test.c*/

#includestdio.h>

#includestdlib.h>

intmain(intargc,char*argv[])

{

unsignedintx,y;

unsignedlonglongres;

if((argc3)||(sscanf(argv[1],%u,x)!=1)

||(sscanf(argv[2],%u,y))!=1)

{

printf(Usage:powbaseexponentn);

exit(1);

}

res=unsgn_pow(x,y);

printf(%u^%u=%un,x,y,res);

exit(0);

}

linux操作系統(tǒng)文章專題:linux操作系統(tǒng)詳解(linux不再難懂)

linux相關(guān)文章:linux教程


c++相關(guān)文章:c++教程




評論


相關(guān)推薦

技術(shù)專區(qū)

關(guān)閉