<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

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

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

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

          本文引用地址:http://www.ex-cimer.com/article/257151.htm

          (4)鏈接階段。

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

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

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

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

          [root@localhostgcc]#gcchello.o–ohello

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

          [root@localhostgcc]#./hello

          Hello!Thisisourembeddedworld!

          3.3.2gcc編譯選項分析

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

          (1)常用選項。

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

          表3.7 gcc常用選項列表

          選項

          含義

          -c

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

          -S

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

          -E

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

          -g

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

          -ofile

          將file文件指定為輸出文件

          -v

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

          -Idir

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

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

          n “-Idir”

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

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

          /*hello1.c*/

          #includemy.h>

          intmain()

          {

          printf(Hello!!n);

          return0;

          }

          /*my.h*/

          #includestdio.h>

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

          [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”選項了。

          (2)庫選項。

          gcc庫選項如表3.8所示。

          表3.8 gcc庫選項列表

          選項

          含義

          -static

          進行靜態(tài)編譯,即鏈接靜態(tài)庫,禁止使用動態(tài)庫

          -shared

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

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

          -Ldir

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

          -lname

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

          -fPIC(或-fpic)

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

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

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

          下面舉一個簡單的例子,講解如何怎么創(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文件,它會調(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)閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();