Linux下C語言編程收_第1頁
Linux下C語言編程收_第2頁
Linux下C語言編程收_第3頁
Linux下C語言編程收_第4頁
Linux下C語言編程收_第5頁
已閱讀5頁,還剩10頁未讀 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

1、Linux 下 C 語言編程 收Linux下C語言編程-收2010-06-24 09:52原著:Rick McMullin前言Linux的發(fā)行版中包含了很多軟件開發(fā)工具.它們中的很多是用于C和C+應用程序開發(fā)的.本文介紹了在Linux下能用于C應用程序開發(fā)和調(diào)試的工具.本文的主旨是介紹如何在Linux下使用C編譯器和其他C編程工具,而非C語言編程的教程.在本文中你將學到以下知識:什么是CGNU C編譯器用gdb來調(diào)試GCC應用程序你也能看到隨Linux發(fā)行的其他有用的C編程工具.這些工具包括源程序美化程序(pretty print programs),附加的調(diào)試工具,函數(shù)原型自動生成工具(au

2、tomatic function prototypers).源程序美化程序(pretty print programs)自動幫你格式化源代碼產(chǎn)生始終如一的縮進格式.什么是C?C是一種在UNIX操作系統(tǒng)的早期就被廣泛使用的通用編程語言.它最早是由貝爾實驗室的Dennis Ritchie為了UNIX的輔助開發(fā)而寫的,開始時UNIX是用匯編語言和一種叫B的語言編寫的.從那時候起,C就成為世界上使用最廣泛計算機語言.C能在編程領(lǐng)域里得到如此廣泛支持的原因有以下一些:它是一種非常通用的語言.幾乎你所能想到的任何一種計算機上都有至少一種能用的C編譯器.并且它的語法和函數(shù)庫在不同的平臺上都是統(tǒng)一的,這個特性

3、對開發(fā)者來說很有吸引力.用C寫的程序執(zhí)行速度很快.C是所有版本的UNIX上的系統(tǒng)語言.C在過去的二十年中有了很大的發(fā)展.在80年代末期美國國家標準協(xié)會(American National Standards Institute)發(fā)布了一個被稱為ANSI C的C語言標準.這更加保證了將來在不同平臺上的C的一致性.在80年代還出現(xiàn)了一種C的面向?qū)ο蟮臄U展稱為C+.C+將在另一篇文章C+編程中描述.Linux上可用的C編譯器是GNU C編譯器,它建立在自由軟件基金會的編程許可證的基礎上,因此可以自由發(fā)布.你能在Linux的發(fā)行光盤上找到它.GNU C編譯器隨Slackware Linux發(fā)行的GNU

4、 C編譯器(GCC)是一個全功能的ANSI C兼容編譯器.如果你熟悉其他操作系統(tǒng)或硬件平臺上的一種C編譯器,你將能很快地掌握GCC.本節(jié)將介紹如何使用GCC和一些GCC編譯器最常用的選項.使用GCC通常后跟一些選項和文件名來使用GCC編譯器.gcc命令的基本用法如下:gccoptionsfilenames命令行選項指定的操作將在命令行上每個給出的文件上執(zhí)行.下一小節(jié)將敘述一些你會最常用到的選項.GCC選項GCC有超過100個的編譯選項可用.這些選項中的許多你可能永遠都不會用到,但一些主要的選項將會頻繁用到.很多的GCC選項包括一個以上的字符.因此你必須為每個選項指定各自的連字符,并且就象大多數(shù)

5、Linux命令一樣你不能在一個單獨的連字符后跟一組選項.例如,下面的兩個命令是不同的:gcc-p-g test.c gcc-pg test.c第一條命令告訴GCC編譯test.c時為prof命令建立剖析(profile)信息并且把調(diào)試信息加入到可執(zhí)行的文件里.第二條命令只告訴GCC為gprof命令建立剖析信息.當你不用任何選項編譯一個程序時,GCC將會建立(假定編譯成功)一個名為a.out的可執(zhí)行文件.例如,下面的命令將在當前目錄下產(chǎn)生一個叫a.out的文件:gcc test.c你能用-o編譯選項來為將產(chǎn)生的可執(zhí)行文件指定一個文件名來代替a.out.例如,將一個叫count.c的C程序編譯為名

6、叫count的可執(zhí)行文件,你將輸入下面的命令:gcc-o count count.c當你使用-o選項時,-o后面必須跟一個文件名.GCC同樣有指定編譯器處理多少的編譯選項.-c選項告訴GCC僅把源代碼編譯為目標代碼而跳過匯編和連接的步驟.這個選項使用的非常頻繁因為它使得編譯多個C程序時速度更快并且更易于管理.缺省時GCC建立的目標代碼文件有一個.o的擴展名.-S編譯選項告訴GCC在為C代碼產(chǎn)生了匯編語言文件后停止編譯.GCC產(chǎn)生的匯編語言文件的缺省擴展名是.s.-E選項指示編譯器僅對輸入文件進行預處理.當這個選項被使用時,預處理器的輸出被送到標準輸出而不是儲存在文件里.優(yōu)化選項當你用GCC編譯

7、C代碼時,它會試著用最少的時間完成編譯并且使編譯后的代碼易于調(diào)試.易于調(diào)試意味著編譯后的代碼與源代碼有同樣的執(zhí)行次序,編譯后的代碼沒有經(jīng)過優(yōu)化.有很多選項可用于告訴GCC在耗費更多編譯時間和犧牲易調(diào)試性的基礎上產(chǎn)生更小更快的可執(zhí)行文件.這些選項中最典型的是-O和-O2選項.-O選項告訴GCC對源代碼進行基本優(yōu)化.這些優(yōu)化在大多數(shù)情況下都會使程序執(zhí)行的更快.-O2選項告訴GCC產(chǎn)生盡可能小和盡可能快的代碼.-O2選項將使編譯的速度比使用-O時慢.但通常產(chǎn)生的代碼執(zhí)行速度會更快.除了-O和-O2優(yōu)化選項外,還有一些低級選項用于產(chǎn)生更快的代碼.這些選項非常的特殊,而且最好只有當你完全理解這些選項將會

8、對編譯后的代碼產(chǎn)生什么樣的效果時再去使用.這些選項的詳細描述,請參考GCC的指南頁,在命令行上鍵入man gcc.調(diào)試和剖析選項GCC支持數(shù)種調(diào)試和剖析選項.在這些選項里你會最常用到的是-g和-pg選項.-g選項告訴GCC產(chǎn)生能被GNU調(diào)試器使用的調(diào)試信息以便調(diào)試你的程序.GCC提供了一個很多其他C編譯器里沒有的特性,在GCC里你能使-g和-O(產(chǎn)生優(yōu)化代碼)聯(lián)用.這一點非常有用因為你能在與最終產(chǎn)品盡可能相近的情況下調(diào)試你的代碼.在你同時使用這兩個選項時你必須清楚你所寫的某些代碼已經(jīng)在優(yōu)化時被GCC作了改動.關(guān)于調(diào)試C程序的更多信息請看下一節(jié)用gdb調(diào)試C程序.-pg選項告訴GCC在你的程序里

9、加入額外的代碼,執(zhí)行時,產(chǎn)生gprof用的剖析信息以顯示你的程序的耗時情況.關(guān)于gprof的更多信息請參考gprof一節(jié).用gdb調(diào)試GCC程序Linux包含了一個叫g(shù)db的GNU調(diào)試程序.gdb是一個用來調(diào)試C和C+程序的強力調(diào)試器.它使你能在程序運行時觀察程序的內(nèi)部結(jié)構(gòu)和內(nèi)存的使用情況.以下是gdb所提供的一些功能:它使你能監(jiān)視你程序中變量的值.它使你能設置斷點以使程序在指定的代碼行上停止執(zhí)行.它使你能一行行的執(zhí)行你的代碼.在命令行上鍵入gdb并按回車鍵就可以運行g(shù)db了,如果一切正常的話,gdb將被啟動并且你將在屏幕上看到類似的內(nèi)容:GDB is free software and yo

10、u are welcome to distribute copies of it under certain conditions;typeshow copyingto see the conditions.There is absolutely no warranty for GDB;typeshow warrantyfor details.GDB 4.14(i486-slakware-linux),Copyright 1995 Free Software Foundation,Inc.(gdb)當你啟動gdb后,你能在命令行上指定很多的選項.你也可以以下面的方式來運行g(shù)db:gdb fna

11、me當你用這種方式運行g(shù)db,你能直接指定想要調(diào)試的程序.這將告訴gdb裝入名為fname的可執(zhí)行文件.你也可以用gdb去檢查一個因程序異常終止而產(chǎn)生的core文件,或者與一個正在運行的程序相連.你可以參考gdb指南頁或在命令行上鍵入gdb-h得到一個有關(guān)這些選項的說明的簡單列表.為調(diào)試編譯代碼(Compiling Code for Debugging)為了使gdb正常工作,你必須使你的程序在編譯時包含調(diào)試信息.調(diào)試信息包含你程序里的每個變量的類型和在可執(zhí)行文件里的地址映射以及源代碼的行號.gdb利用這些信息使源代碼和機器碼相關(guān)聯(lián).在編譯時用-g選項打開調(diào)試選項.gdb基本命令gdb支持很多的

12、命令使你能實現(xiàn)不同的功能.這些命令從簡單的文件裝入到允許你檢查所調(diào)用的堆棧內(nèi)容的復雜命令,表27.1列出了你在用gdb調(diào)試時會用到的一些命令.想了解gdb的詳細使用請參考gdb的指南頁.表27.1.基本gdb命令.命令描述file裝入想要調(diào)試的可執(zhí)行文件.kill終止正在調(diào)試的程序.list列出產(chǎn)生執(zhí)行文件的源代碼的一部分.next執(zhí)行一行源代碼但不進入函數(shù)內(nèi)部.step執(zhí)行一行源代碼而且進入函數(shù)內(nèi)部.run執(zhí)行當前被調(diào)試的程序quit終止gdb watch使你能監(jiān)視一個變量的值而不管它何時被改變.break在代碼里設置斷點,這將使程序執(zhí)行到這里時被掛起.make使你能不退出gdb就可以重新產(chǎn)

13、生可執(zhí)行文件.shell使你能不離開gdb就執(zhí)行UNIX shell命令.gdb支持很多與UNIX shell程序一樣的命令編輯特征.你能象在bash或tcsh里那樣按Tab鍵讓gdb幫你補齊一個唯一的命令,如果不唯一的話gdb會列出所有匹配的命令.你也能用光標鍵上下翻動歷史命令.gdb應用舉例本節(jié)用一個實例教你一步步的用gdb調(diào)試程序.被調(diào)試的程序相當?shù)暮唵?但它展示了gdb的典型應用.下面列出了將被調(diào)試的程序.這個程序被稱為greeting,它顯示一個簡單的問候,再用反序?qū)⑺谐?#include stdio.h main()char my_string=hello there;my_pr

14、int(my_string);my_print2(my_string);void my_print(char*string)printf(The string is%sn,string);void my_print2(char*string)char*string2;int size,i;size=strlen(string);string2=(char*)malloc(size+1);for(i=0;i size;i+)string2size-i=stringi;string2size+1=message;printf(The string printed backward is%sn,st

15、ring2);用下面的命令編譯它:gcc-o test test.c這個程序執(zhí)行時顯示如下結(jié)果:The string is hello there The string printed backward is輸出的第一行是正確的,但第二行打印出的東西并不是我們所期望的.我們所設想的輸出應該是:The string printed backward is ereht olleh由于某些原因,my_print2函數(shù)沒有正常工作.讓我們用gdb看看問題究竟出在哪兒,先鍵入如下命令:gdb greeting記得在編譯greeting程序時把調(diào)試選項打開.如果你在輸入命令時忘了把要調(diào)試的程序作為參數(shù)傳給

16、gdb,你可以在gdb提示符下用file命令來載入它:(gdb)file greeting這個命令將載入greeting可執(zhí)行文件就象你在gdb命令行里裝入它一樣.這時你能用gdb的run命令來運行g(shù)reeting了.當它在gdb里被運行后結(jié)果大約會象這樣:(gdb)run Starting program:/root/greeting The string is hello there The string printed backward is Program exited with code 041這個輸出和在gdb外面運行的結(jié)果一樣.問題是,為什么反序打印沒有工作?為了找出癥結(jié)所在,我

17、們可以在my_print2函數(shù)的for語句后設一個斷點,具體的做法是在gdb提示符下鍵入list命令三次,列出源代碼:(gdb)list(gdb)list(gdb)list技巧:在gdb提示符下按回車健將重復上一個命令.第一次鍵入list命令的輸出如下:1#include stdio.h 3main()45 char my_string=hello there;7 my_print(my_string);8 my_print2(my_string);910如果按下回車,gdb將再執(zhí)行一次list命令,給出下列輸出:11 my_print(char*string)1213 printf(The

18、string is%sn,string);1415 16 my_print2(char*string)1718 char*string2;19 int size,i;20再按一次回車將列出greeting程序的剩余部分:21 size=strlen(string);22 string2=(char*)malloc(size+1);23 for(i=0;i size;i+)24 string2size-i=stringi;25 string2size+1=message;26 printf(The string printed backward is%sn,string2);27根據(jù)列出的源程序

19、,你能看到要設斷點的地方在第24行,在gdb命令行提示符下鍵入如下命令設置斷點:(gdb)break 24 gdb將作出如下的響應:Breakpoint 1at 0x139:file greeting.c,line 24(gdb)現(xiàn)在再鍵入run命令,將產(chǎn)生如下的輸出:Starting program:/root/greeting The string is hello there Breakpoint 1,my_print2(string=0xbfffdc4hello there)at greeting.c:24 24 string2size-i=stringi你能通過設置一個觀察strin

20、g2size-i變量的值的觀察點來看出錯誤是怎樣產(chǎn)生的,做法是鍵入:(gdb)watch string2size-igdb將作出如下回應:Watchpoint 2:string2size-i現(xiàn)在可以用next命令來一步步的執(zhí)行for循環(huán)了:(gdb)next經(jīng)過第一次循環(huán)后,gdb告訴我們string2size-i的值是h.gdb用如下的顯示來告訴你這個信息:Watchpoint 2,string2size-iOld value=0message0New value=104hmy_print2(string=0xbfffdc4hello there)at greeting.c:23 23 fo

21、r(i=0;i size;i+)這個值正是期望的.后來的數(shù)次循環(huán)的結(jié)果都是正確的.當i=10時,表達式string2size-i的值等于e,size-i的值等于1,最后一個字符已經(jīng)拷到新串里了.如果你再把循環(huán)執(zhí)行下去,你會看到已經(jīng)沒有值分配給string20了,而它是新串的第一個字符,因為malloc函數(shù)在分配內(nèi)存時把它們初始化為空(null)字符.所以string2的第一個字符是空字符.這解釋了為什么在打印string2時沒有任何輸出了.現(xiàn)在找出了問題出在哪里,修正這個錯誤是很容易的.你得把代碼里寫入string2的第一個字符的的偏移量改為size-1而不是size.這是因為string2的

22、大小為12,但起始偏移量是0,串內(nèi)的字符從偏移量0到偏移量10,偏移量11為空字符保留.為了使代碼正常工作有很多種修改辦法.一種是另設一個比串的實際大小小1的變量.這是這種解決辦法的代碼:#include stdio.h main()char my_string=hello there;my_print(my_string);my_print2(my_string);my_print(char*string)printf(The string is%sn,string);my_print2(char*string)char*string2;int size,size2,i;size=strle

23、n(string);size2=size-1;string2=(char*)malloc(size+1);for(i=0;i size;i+)string2size2-i=stringi;string2size=message;printf(The string printed backward is%sn,string2);另外的C編程工具Slackware Linux的發(fā)行版中還包括一些我們尚未提到的C開發(fā)工具.本節(jié)將介紹這些工具和它們的典型用法.xxgdb xxgdb是gdb的一個基于X Window系統(tǒng)的圖形界面.xxgdb包括了命令行版的gdb上的所有特性.xxgdb使你能通過按按鈕

24、來執(zhí)行常用的命令.設置了斷點的地方也用圖形來顯示.你能在一個Xterm窗口里鍵入下面的命令來運行它:xxgdb你能用gdb里任何有效的命令行選項來初始化xxgdb.此外xxgdb也有一些特有的命令行選項,表27.2列出了這些選項.表27.2.xxgdb命令行選項.描述db_name指定所用調(diào)試器的名字,缺省是gdb.db_prompt指定調(diào)試器提示符,缺省為gdb.gdbinit指定初始化gdb的命令文件的文件名,缺省為.gdbinit.nx告訴xxgdb不執(zhí)行.gdbinit文件.bigicon使用大圖標.calls你可以在 FTP站點用下面的路徑:/pub/L

25、inux/devel/lang/c/calls.tar.Z來取得calls,一些舊版本的Linux CD-ROM發(fā)行版里也附帶有.因為它是一個有用的工具,我們在這里也介紹一下.如果你覺得有用的話,從BBS,FTP,或另一張CD-ROM上弄一個拷貝.calls調(diào)用GCC的預處理器來處理給出的源程序文件,然后輸出這些文件的里的函數(shù)調(diào)用樹圖.在你的系統(tǒng)上安裝calls,以超級用戶身份登錄后執(zhí)行下面的步驟:1.解壓和untar文件.2.cd進入calls untar后建立的子目錄.3.把名叫calls的文件移動到/usr/bin目錄.4.把名叫calls.1的文件移動到目錄/usr/man/man1.

26、5.刪除/tmp/calls目錄.這些步驟將把calls程序和它的指南頁安裝載你的系統(tǒng)上.當calls打印出調(diào)用跟蹤結(jié)果時,它在函數(shù)后面用中括號給出了函數(shù)所在文件的文件名:maintest.c如果函數(shù)并不是向calls給出的文件里的,calls不知道所調(diào)用的函數(shù)來自哪里,則只顯示函數(shù)的名字:printf calls不對遞歸和靜態(tài)函數(shù)輸出.遞歸函數(shù)顯示成下面的樣子:fact recursive in factorial.c靜態(tài)函數(shù)象這樣顯示:totalstatic in calculate.c作為一個例子,假設用calls處理下面的程序:#include stdio.h main()char m

27、y_string=hello there;my_print(my_string);my_print2(my_string);my_print(char*string)printf(The string is%sn,string);my_print2(char*string)char*string2;int size,size2,i;size=strlen(string);size2=size-1;string2=(char*)malloc(size+1);for(i=0;i size;i+)string2size2-i=stringi;string2size=message;printf(Th

28、e string printed backward is%sn,string2);將產(chǎn)生如下的輸出:1 maintest.c2 my_printtest.c3 printf 4my_print2test.c5 strlen 6malloc 7printfcalls有很多命令行選項來設置不同的輸出格式,有關(guān)這些選項的更多信息請參考calls的指南頁.方法是在命令行上鍵入calls-h.cproto cproto讀入C源程序文件并自動為每個函數(shù)產(chǎn)生原型申明.用cproto可以在寫程序時為你節(jié)省大量用來定義函數(shù)原型的時間.如果你讓cproto處理下面的代碼:#include stdio.h main

29、()char my_string=hello there;my_print(my_string);my_print2(my_string);my_print(char*string)printf(The string is%sn,*string);my_print2(char*string)char*string2;int size,size2,i;size=strlen(string);size2=size-1;string2=(char*)malloc(size+1);for(i=0;i size;i+)string2size2-i=stringi;string2size=message;

30、printf(The string printed backward is%sn,string2);你將得到下面的輸出:/*test.c*/int main(void);int my_print(char*string);int my_print2(char*string);這個輸出可以重定向到一個定義函數(shù)原型的包含文件里.indent indent實用程序是Linux里包含的另一個編程實用工具.這個工具簡單的說就為你的代碼產(chǎn)生美觀的縮進的格式.indent也有很多選項來指定如何格式化你的源代碼.這些選項的更多信息請看indent的指南頁,在命令行上鍵入indent-h.下面的例子是inden

31、t的缺省輸出:運行indent以前的C代碼:#include stdio.h main()char my_string=hello there;my_print(my_string);my_print2(my_string);my_print(char*string)printf(The string is%sn,*string);my_print2(char*string)char*string2;int size,size2,i;size=strlen(string);size2=size-1;string2=(char*)malloc(size+1);for(i=0;i size;i+)string2size2-i=stringi;string2size=message;printf(The string printed backward is%sn,string2);運行indent后的C代碼:#include stdio.h main()char my_string=hello there;my_print(my_string);my_print2(my_string);my_print(char*string)printf(The string is%sn,*string);my_print2(char*string)char*

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論