


Linux 下 C 語言編程
· 什么是 C
· GNU C 編譯器
· 用 gdb 來調(diào)試GCC應(yīng)用程序
你也能看到隨 Linux 發(fā)行的其他有用的 C 編程工具。 這些工具包括源程序美化程序(pretty print programs), 附加的調(diào)試工具, 函數(shù)原型自動(dòng)生成工具(automatic function prototypers)。
注意: 源程序美化程序(pretty print programs)自動(dòng)幫你格式化源代碼產(chǎn)生始終如一的縮進(jìn)格式。
什么是 C?
C 是一種在 UNIX 操作系統(tǒng)的早期就被廣泛使用的通用編程語言。 它最早是由貝爾實(shí)驗(yàn)室的 Dennis Ritchie 為了 UNIX 的輔助開發(fā)而寫的, 開始時(shí) UNIX 是用匯編語言和一種叫 B 的語言編寫的。 從那時(shí)候起, C 就成為世界上使用最廣泛計(jì)算機(jī)語言。
C 能在編程領(lǐng)域里得到如此廣泛支持的原因有以下一些:
· 它是一種非常通用的語言。 幾乎你所能想到的任何一種計(jì)算機(jī)上都有至少一種能用的 C 編譯器。 并且它的語法和函數(shù)庫在不同的平臺(tái)上都是統(tǒng)一的, 這個(gè)特性對(duì)開發(fā)者來說很有吸引力。
· 用 C 寫的程序執(zhí)行速度很快。
· C 是所有版本的UNIX上的系統(tǒng)語言。
C 在過去的二十年中有了很大的發(fā)展。 在80年代末期美國國家標(biāo)準(zhǔn)協(xié)會(huì)(American National Standards Institute)發(fā)布了一個(gè)被稱為 ANSI C 的 C 語言標(biāo)準(zhǔn)。這更加保證了將來在不同平臺(tái)上的 C 的一致性。 在80年代還出現(xiàn)了一種 C 的面向?qū)ο蟮臄U(kuò)展稱為 C++。 C++ 將在另一篇文章 "C++ 編程"中描述。
Linux 上可用的 C 編譯器是 GNU C 編譯器, 它建立在自由軟件基金會(huì)的編程許可證的基礎(chǔ)上, 因此可以自由發(fā)布。 你能在 Linux 的發(fā)行光盤上找到它。
GNU C 編譯器
隨 Slackware Linux 發(fā)行的 GNU C 編譯器(GCC)是一個(gè)全功能的 ANSI C 兼容編譯器。 如果你熟悉其他操作系統(tǒng)或硬件平臺(tái)上的一種 C 編譯器, 你將能很快地掌握 GCC。 本節(jié)將介紹如何使用 GCC 和一些 GCC 編譯器最常用的選項(xiàng)。
使用 GCC
通常后跟一些選項(xiàng)和文件名來使用 GCC 編譯器。 gcc 命令的基本用法如下:
gcc [options] [filenames]
命令行選項(xiàng)指定的操作將在命令行上每個(gè)給出的文件上執(zhí)行。 下一小節(jié)將敘述一些你會(huì)最常用到的選項(xiàng)。
GCC 選項(xiàng)
GCC 有超過100個(gè)的編譯選項(xiàng)可用。 這些選項(xiàng)中的許多你可能永遠(yuǎn)都不會(huì)用到, 但一些主要的選項(xiàng)將會(huì)頻繁用到。 很多的 GCC 選項(xiàng)包括一個(gè)以上的字符。 因此你必須為每個(gè)選項(xiàng)指定各自的連字符, 并且就象大多數(shù) Linux 命令一樣你不能在一個(gè)單獨(dú)的連字符后跟一組選項(xiàng)。 例如, 下面的兩個(gè)命令是不同的:
gcc -p -g test.c
gcc -pg test.c
第一條命令告訴 GCC 編譯 test.c 時(shí)為 prof 命令建立剖析(profile)信息并且把調(diào)試信息加入到可執(zhí)行的文件里。 第二條命令只告訴
GCC 為 gprof 命令建立剖析信息。
當(dāng)你不用任何選項(xiàng)編譯一個(gè)程序時(shí), GCC 將會(huì)建立(假定編譯成功)一個(gè)名為 a.out 的可執(zhí)行文件。 例如, 下面的命令將在當(dāng)前目錄下產(chǎn)生一個(gè)叫 a.out 的文件:
gcc test.c
你能用 -o 編譯選項(xiàng)來為將產(chǎn)生的可執(zhí)行文件指定一個(gè)文件名來代替 a.out。 例如, 將一個(gè)叫 count.c 的 C 程序編譯為名叫 count 的可執(zhí)行文件, 你將輸入下面的命令:
gcc -o count count.c
注意: 當(dāng)你使用 -o 選項(xiàng)時(shí), -o 后面必須跟一個(gè)文件名。
GCC 同樣有指定編譯器處理多少的編譯選項(xiàng)。 -c 選項(xiàng)告訴 GCC 僅把源代碼編譯為目標(biāo)代碼而跳過匯編和連接的步驟。 這個(gè)選項(xiàng)使用的非常頻繁因?yàn)樗沟镁幾g多個(gè) C 程序時(shí)速度更快并且更易于管理。 缺省時(shí) GCC 建立的目標(biāo)代碼文件有一個(gè) .o 的擴(kuò)展名。
-S 編譯選項(xiàng)告訴 GCC 在為 C 代碼產(chǎn)生了匯編語言文件后停止編譯。 GCC 產(chǎn)生的匯編語言文件的缺省擴(kuò)展名是 .s 。 -E 選項(xiàng)指示編譯器僅對(duì)輸入文件進(jìn)行預(yù)處理。 當(dāng)這個(gè)選項(xiàng)被使用時(shí), 預(yù)處理器的輸出被送到標(biāo)準(zhǔn)輸出而不是儲(chǔ)存在文件里。
優(yōu)化選項(xiàng)
當(dāng)你用 GCC 編譯 C 代碼時(shí), 它會(huì)試著用最少的時(shí)間完成編譯并且使編譯后的代碼易于調(diào)試。 易于調(diào)試意味著編譯后的代碼與源代碼有同樣的執(zhí)行次序, 編譯后的代碼沒有經(jīng)過優(yōu)化。 有很多選項(xiàng)可用于告訴 GCC 在耗費(fèi)更多編譯時(shí)間和犧牲易調(diào)試性的基礎(chǔ)上產(chǎn)生更小更快的可執(zhí)行文件。 這些選項(xiàng)中最典型的是-O 和 -O2 選項(xiàng)。
-O 選項(xiàng)告訴 GCC 對(duì)源代碼進(jìn)行基本優(yōu)化。 這些優(yōu)化在大多數(shù)情況下都會(huì)使程序執(zhí)行的更快。 -O2 選項(xiàng)告訴 GCC 產(chǎn)生盡可能小和盡可能快的代碼。 -O2 選項(xiàng)將使編譯的速度比使用 -O 時(shí)慢。 但通常產(chǎn)生的代碼執(zhí)行速度會(huì)更快。
除了 -O 和 -O2 優(yōu)化選項(xiàng)外, 還有一些低級(jí)選項(xiàng)用于產(chǎn)生更快的代碼。 這些選項(xiàng)非常的特殊, 而且最好只有當(dāng)你完全理解這些選項(xiàng)將會(huì)對(duì)編譯后的代碼產(chǎn)生什么樣的效果時(shí)再去使用。 這些選項(xiàng)的詳細(xì)描述, 請(qǐng)參考 GCC 的指南頁, 在命令行上鍵入 man gcc 。
調(diào)試和剖析選項(xiàng)
GCC 支持?jǐn)?shù)種調(diào)試和剖析選項(xiàng)。 在這些選項(xiàng)里你會(huì)最常用到的是 -g 和 -pg 選項(xiàng)。
-g 選項(xiàng)告訴 GCC 產(chǎn)生能被 GNU 調(diào)試器使用的調(diào)試信息以便調(diào)試你的程序。 GCC 提供了一個(gè)很多其他 C 編譯器里沒有的特性, 在 GCC 里你能使 -g 和 -O (產(chǎn)生優(yōu)化代碼)聯(lián)用。 這一點(diǎn)非常有用因?yàn)槟隳茉谂c最終產(chǎn)品盡可能相近的情況下調(diào)試你的代碼。 在你同時(shí)使用這兩個(gè)選項(xiàng)時(shí)你必須清楚你所寫的某些代碼已經(jīng)在優(yōu)化時(shí)被 GCC 作了改動(dòng)。 關(guān)于調(diào)試 C 程序的更多信息請(qǐng)看下一節(jié)"用 gdb 調(diào)試 C 程序" 。
-pg 選項(xiàng)告訴 GCC 在你的程序里加入額外的代碼, 執(zhí)行時(shí), 產(chǎn)生 gprof 用的剖析信息以顯示你的程序的耗時(shí)情況。 關(guān)于 gprof 的更多信息請(qǐng)參考 "gprof" 一節(jié)。
用 gdb 調(diào)試 GCC 程序
Linux 包含了一個(gè)叫 gdb 的 GNU 調(diào)試程序。 gdb 是一個(gè)用來調(diào)試 C 和 C++ 程序的強(qiáng)力調(diào)試器。 它使你能在程序運(yùn)行時(shí)觀察程序的內(nèi)部結(jié)構(gòu)和內(nèi)存的使用情況。 以下是 gdb 所提供的一些功能:
· 它使你能監(jiān)視你程序中變量的值。
· 它使你能設(shè)置斷點(diǎn)以使程序在指定的代碼行上停止執(zhí)行。
· 它使你能一行行的執(zhí)行你的代碼。
在命令行上鍵入 gdb 并按回車鍵就可以運(yùn)行 gdb 了, 如果一切正常的話, gdb 將被啟動(dòng)并且你將在屏幕上看到類似的內(nèi)容:
GDB is free software and you are welcome to distribute copies of it
under certain conditions; type "show copying" to see the conditions.
There is absolutely no warranty for GDB; type "show warranty" for details.
GDB 4.14 (i486-slakware-linux), Copyright 1995 Free Software Foundation, Inc.
(gdb)
當(dāng)你啟動(dòng) gdb 后, 你能在命令行上指定很多的選項(xiàng)。 你也可以以下面的方式來運(yùn)行 gdb :
gdb
當(dāng)你用這種方式運(yùn)行 gdb , 你能直接指定想要調(diào)試的程序。 這將告訴gdb 裝入名為 fname 的可執(zhí)行文件。 你也可以用 gdb 去檢查一個(gè)因程序異常終止而產(chǎn)生的 core 文件, 或者與一個(gè)正在運(yùn)行的程序相連。 你可以參考 gdb 指南頁或在命令行上鍵入 gdb -h 得到一個(gè)有關(guān)這些選項(xiàng)的說明的簡(jiǎn)單列表。
為調(diào)試編譯代碼(Compiling Code for Debugging)
為了使 gdb 正常工作, 你必須使你的程序在編譯時(shí)包含調(diào)試信息。 調(diào)試信息包含你程序里的每個(gè)變量的類型和在可執(zhí)行文件里的地址映射以及源代碼的行號(hào)。 gdb 利用這些信息使源代碼和機(jī)器碼相關(guān)聯(lián)。
在編譯時(shí)用 -g 選項(xiàng)打開調(diào)試選項(xiàng)。
gdb 基本命令
gdb 支持很多的命令使你能實(shí)現(xiàn)不同的功能。 這些命令從簡(jiǎn)單的文件裝入到允許你檢查所調(diào)用的堆棧內(nèi)容的復(fù)雜命令, 表27.1列出了你在用 gdb 調(diào)試時(shí)會(huì)用到的一些命令。 想了解 gdb 的詳細(xì)使用請(qǐng)參考 gdb 的指南頁。
表 27.1. 基本 gdb 命令.
命令描述 | |
file | 裝入想要調(diào)試的可執(zhí)行文件。 |
kill | 終止正在調(diào)試的程序。 |
list | 執(zhí)行一行源代碼但不進(jìn)入函數(shù)內(nèi)部。 |
next | 執(zhí)行一行源代碼但不進(jìn)入函數(shù)內(nèi)部。 |
step | 執(zhí)行一行源代碼而且進(jìn)入函數(shù)內(nèi)部。 |
run | 執(zhí)行當(dāng)前被調(diào)試的程序 |
quit | 終止 gdb |
watch | 使你能監(jiān)視一個(gè)變量的值而不管它何時(shí)被改變。 |
break | 在代碼里設(shè)置斷點(diǎn), 這將使程序執(zhí)行到這里時(shí)被掛起。 |
make | 使你能不退出 gdb 就可以重新產(chǎn)生可執(zhí)行文件。 |
shell | 使你能不離開 gdb 就執(zhí)行 UNIX shell 命令。 |
gdb 支持很多與 UNIX shell 程序一樣的命令編輯特征。 你能象在 bash 或 tcsh里那樣按 Tab 鍵讓 gdb 幫你補(bǔ)齊一個(gè)唯一的命令, 如果不唯一的話 gdb 會(huì)列出所有匹配的命令。 你也能用光標(biāo)鍵上下翻動(dòng)歷史命令。
gdb 應(yīng)用舉例
本節(jié)用一個(gè)實(shí)例教你一步步的用 gdb 調(diào)試程序。 被調(diào)試的程序相當(dāng)?shù)暮?jiǎn)單, 但它展示了 gdb 的典型應(yīng)用。
下面列出了將被調(diào)試的程序。 這個(gè)程序被稱為 greeting , 它顯示一個(gè)簡(jiǎn)單的問候, 再用反序?qū)⑺谐觥?nbsp;
#include main () { char my_string[] = "hello there"; my_print (my_string); my_print2 (my_string); } void my_print (char *string) { printf ("The string is %s\n", 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++) string2[size - i] = string[i]; string2[size+1] = `%content%'; printf ("The string printed backward is %s\n", string2); } |
用下面的命令編譯它:
gcc -o test test.c
這個(gè)程序執(zhí)行時(shí)顯示如下結(jié)果:
The string is hello there
The string printed backward is
輸出的第一行是正確的, 但第二行打印出的東西并不是我們所期望的。 我們所設(shè)想的輸出應(yīng)該是:
The string printed backward is ereht olleh
由于某些原因, my_print2 函數(shù)沒有正常工作。 讓我們用 gdb 看看問題究竟出在哪兒, 先鍵入如下命令:
gdb greeting
注意: 記得在編譯 greeting 程序時(shí)把調(diào)試選項(xiàng)打開。
如果你在輸入命令時(shí)忘了把要調(diào)試的程序作為參數(shù)傳給 gdb , 你可以在 gdb 提示符下用 file 命令來載入它:
(gdb) file greeting
這個(gè)命令將載入 greeting 可執(zhí)行文件就象你在 gdb 命令行里裝入它一樣。
這時(shí)你能用 gdb 的 run 命令來運(yùn)行 greeting 了。 當(dāng)它在 gdb 里被運(yùn)行后結(jié)果大約會(huì)象這樣:
(gdb) run Starting program: /root/greeting The string is hello there The string printed backward is Program exited with code 041 |
這個(gè)輸出和在 gdb 外面運(yùn)行的結(jié)果一樣。 問題是, 為什么反序打印沒有工作? 為了找出癥結(jié)所在, 我們可以在 my_print2 函數(shù)的 for 語句后設(shè)一個(gè)斷點(diǎn), 具體的做法是在 gdb 提示符下鍵入 list 命令三次, 列出源代碼:
(gdb) list
(gdb) list
(gdb) list
技巧: 在 gdb 提示符下按回車健將重復(fù)上一個(gè)命令。
第一次鍵入 list 命令的輸出如下:
1 #include 2 3 main () 4 { 5 char my_string[] = "hello there"; 6 7 my_print (my_string); 8 my_print2 (my_string); 9 } 10 |
如果按下回車, gdb 將再執(zhí)行一次 list 命令, 給出下列輸出:
11 my_print (char *string) 12 { 13 printf ("The string is %s\n", string); 14 } 15 16 my_print2 (char *string) 17 { 18 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 string2[size - i] = string[i]; 25 string2[size+1] = `%content%'; 26 printf ("The string printed backward is %s\n", string2); 27 } |
根據(jù)列出的源程序, 你能看到要設(shè)斷點(diǎn)的地方在第24行, 在 gdb 命令行提示符下鍵入如下命令設(shè)置斷點(diǎn):
(gdb) break 24
gdb 將作出如下的響應(yīng):
Breakpoint 1 at 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 = 0xbfffdc4 "hello there") at greeting.c :24 24 string2[size-i]=string[i] |
你能通過設(shè)置一個(gè)觀察 string2[size - i] 變量的值的觀察點(diǎn)來看出錯(cuò)誤是怎樣產(chǎn)生的, 做法是鍵入:
(gdb) watch string2[size - i]
gdb 將作出如下回應(yīng):
Watchpoint 2: string2[size - i]
現(xiàn)在可以用 next 命令來一步步的執(zhí)行 for 循環(huán)了:
(gdb) next
經(jīng)過第一次循環(huán)后, gdb 告訴我們 string2[size - i] 的值是 `h`。 gdb 用如下的顯示來告訴你這個(gè)信息:
Watchpoint 2, string2[size - i] Old value = 0 `%content%00' New value = 104 `h' my_print2(string = 0xbfffdc4 "hello there") at greeting.c:23 23 for (i=0; i |
這個(gè)值正是期望的。 后來的數(shù)次循環(huán)的結(jié)果都是正確的。 當(dāng) i=10 時(shí), 表達(dá)式 string2[size - i] 的值等于 `e`, size - i 的值等于 1, 最后一個(gè)字符已經(jīng)拷到新串里了。
如果你再把循環(huán)執(zhí)行下去, 你會(huì)看到已經(jīng)沒有值分配給 string2[0] 了, 而它是新串的第一個(gè)字符, 因?yàn)?malloc 函數(shù)在分配內(nèi)存時(shí)把它們初始化為空(null)字符。 所以 string2 的第一個(gè)字符是空字符。 這解釋了為什么在打印 string2 時(shí)沒有任何輸出了。
現(xiàn)在找出了問題出在哪里, 修正這個(gè)錯(cuò)誤是很容易的。 你得把代碼里寫入 string2 的第一個(gè)字符的的偏移量改為 size - 1 而不是 size。 這是因?yàn)?string2 的大小為 12, 但起始偏移量是 0, 串內(nèi)的字符從偏移量 0 到 偏移量 10, 偏移量 11 為空字符保留。
為了使代碼正常工作有很多種修改辦法。 一種是另設(shè)一個(gè)比串的實(shí)際大小小 1 的變量。 這是這種解決辦法的代碼:
#include main () { char my_string[] = "hello there"; my_print (my_string); my_print2 (my_string); } my_print (char *string) { printf ("The string is %s\n", 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++) string2[size2 - i] = string[i]; string2[size] = `%content%'; printf ("The string printed backward is %s\n", string2); } |
另外的 C 編程工具
Slackware Linux 的發(fā)行版中還包括一些我們尚未提到的 C 開發(fā)工具。 本節(jié)將介紹這些工具和它們的典型用法。
xxgdb
xxgdb 是 gdb 的一個(gè)基于 X Window 系統(tǒng)的圖形界面。 xxgdb 包括了命令行版的 gdb 上的所有特性。 xxgdb 使你能通過按按鈕來執(zhí)行常用的命令。 設(shè)置了斷點(diǎn)的地方也用圖形來顯示。
你能在一個(gè) Xterm 窗口里鍵入下面的命令來運(yùn)行它:
xxgdb
你能用 gdb 里任何有效的命令行選項(xiàng)來初始化 xxgdb 。 此外 xxgdb 也有一些特有的命令行選項(xiàng), 表 27.2 列出了這些選項(xiàng)。
表 27.2. xxgdb 命令行選項(xiàng). | |
選 項(xiàng) | 描 述 |
db_name | 指定所用調(diào)試器的名字, 缺省是 gdb。 |
db_prompt | 指定調(diào)試器提示符, 缺省為 gdb。 |
gdbinit | 指定初始化 gdb 的命令文件的文件名, 缺省為 .gdbinit。 |
nx | 告訴 xxgdb 不執(zhí)行 .gdbinit 文件。 |
bigicon | 使用大圖標(biāo)。 |
calls
你可以在 sunsite.unc.edu FTP 站點(diǎn)用下面的路徑:
/pub/Linux/devel/lang/c/calls.tar.Z
來取得 calls , 一些舊版本的 Linux CD-ROM 發(fā)行版里也附帶有。 因?yàn)樗且粋€(gè)有用的工具, 我們?cè)谶@里也介紹一下。 如果你覺得有用的話, 從 BBS, FTP, 或另一張CD-ROM 上弄一個(gè)拷貝。 calls 調(diào)用 GCC 的預(yù)處理器來處理給出的源程序文件, 然后輸出這些文件的里的函數(shù)調(diào)用樹圖。
注意: 在你的系統(tǒng)上安裝 calls , 以超級(jí)用戶身份登錄后執(zhí)行下面的步驟: 1. 解壓和 untar 文件。 2.cd 進(jìn)入 calls untar 后建立的子目錄。 3.把名叫 calls 的文件移動(dòng)到 /usr/bin 目錄。 4.把名叫 calls.1 的文件移動(dòng)到目錄 /usr/man/man1 。 5.刪除 /tmp/calls 目錄。 這些步驟將把 calls 程序和它的指南頁安裝載你的系統(tǒng)上。
當(dāng) calls 打印出調(diào)用跟蹤結(jié)果時(shí), 它在函數(shù)后面用中括號(hào)給出了函數(shù)所在文件的文件名:
main [test.c]
如果函數(shù)并不是向 calls 給出的文件里的, calls 不知道所調(diào)用的函數(shù)來自哪里, 則只顯示函數(shù)的名字:
printf
calls 不對(duì)遞歸和靜態(tài)函數(shù)輸出。 遞歸函數(shù)顯示成下面的樣子:
fact <<< recursive in factorial.c >>>
靜態(tài)函數(shù)象這樣顯示:
total [static in calculate.c]
作為一個(gè)例子, 假設(shè)用 calls 處理下面的程序:
#include main () { char my_string[] = "hello there"; my_print (my_string); my_print2(my_string); } my_print (char *string) { printf ("The string is %s\n", 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++) string2[size2 - i] = string[i]; string2[size] = `%content%'; printf ("The string printed backward is %s\n", string2); } |
將產(chǎn)生如下的輸出:
1 main [test.c] 2 my_print [test.c] 3 printf 4 my_print2 [test.c] 5 strlen 6 malloc 7 printf |
calls 有很多命令行選項(xiàng)來設(shè)置不同的輸出格式, 有關(guān)這些選項(xiàng)的更多信息請(qǐng)參考 calls 的指南頁。 方法是在命令行上鍵入 calls -h 。
cproto
cproto 讀入 C 源程序文件并自動(dòng)為每個(gè)函數(shù)產(chǎn)生原型申明。 用 cproto 可以在寫程序時(shí)為你節(jié)省大量用來定義函數(shù)原型的時(shí)間。
如果你讓 cproto 處理下面的代碼:
#include main () { char my_string[] = "hello there"; my_print (my_string); my_print2(my_string); } my_print (char *string) { printf ("The string is %s\n", *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++) string2[size2 - i] = string[i]; string2[size] = `%content%'; printf ("The string printed backward is %s\n", string2); } |
你將得到下面的輸出:
/* test.c */ int main(void); int my_print(char *string); int my_print2(char *string); |
這個(gè)輸出可以重定向到一個(gè)定義函數(shù)原型的包含文件里。
indent
indent 實(shí)用程序是 Linux 里包含的另一個(gè)編程實(shí)用工具。 這個(gè)工具簡(jiǎn)單的說就為你的代碼產(chǎn)生美觀的縮進(jìn)的格式。 indent 也有很多選項(xiàng)來指定如何格式化你的源代碼。這些選項(xiàng)的更多信息請(qǐng)看indent 的指南頁, 在命令行上鍵入 indent -h 。
下面的例子是 indent 的缺省輸出:
運(yùn)行 indent 以前的 C 代碼:
#include main () { char my_string[] = "hello there"; my_print (my_string); my_print2(my_string); } my_print (char *string) { printf ("The string is %s\n", *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++) string2[size2 - i] = string[i]; string2[size] = `%content%'; printf ("The string printed backward is %s\n", string2); } |
運(yùn)行 indent 后的 C 代碼:
#include main () { char my_string[] = "hello there"; my_print (my_string); my_print2 (my_string); } my_print (char *string) { printf ("The string is %s\n", *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++) string2[size2 - i] = string[i]; string2[size] = `%content%'; printf ("The string printed backward is %s\n", string2); } |
indent 并不改變代碼的實(shí)質(zhì)內(nèi)容, 而只是改變代碼的外觀。 使它變得更可讀, 這永遠(yuǎn)是一件好事。
gprof
gprof 是安裝在你的 Linux 系統(tǒng)的 /usr/bin 目錄下的一個(gè)程序。 它使你能剖析你的程序從而知道程序的哪一個(gè)部分在執(zhí)行時(shí)最費(fèi)時(shí)間。
gprof 將告訴你程序里每個(gè)函數(shù)被調(diào)用的次數(shù)和每個(gè)函數(shù)執(zhí)行時(shí)所占時(shí)間的百分比。 你如果想提高你的程序性能的話這些信息非常有用。
為了在你的程序上使用 gprof, 你必須在編譯程序時(shí)加上 -pg 選項(xiàng)。 這將使程序在每次執(zhí)行時(shí)產(chǎn)生一個(gè)叫 gmon.out 的文件。 gprof 用這個(gè)文件產(chǎn)生剖析信息。
在你運(yùn)行了你的程序并產(chǎn)生了 gmon.out 文件后你能用下面的命令獲得剖析信息:
gprof
參數(shù) program_name 是產(chǎn)生 gmon.out 文件的程序的名字。
技巧: gprof 產(chǎn)生的剖析數(shù)據(jù)很大, 如果你想檢查這些數(shù)據(jù)的話最好把輸出重定向到一個(gè)文件里。
f2c 和 p2c
f2c 和 p2c 是兩個(gè)源代碼轉(zhuǎn)換程序。 f2c 把 FORTRAN 代碼轉(zhuǎn)換為 C 代碼, p2c 把 Pascal 代碼轉(zhuǎn)換為 C 代碼。 當(dāng)你安裝 GCC 時(shí)這兩個(gè)程序都會(huì)被安裝上去。
如果你有一些用 FORTRAN 或 Pascal 寫的代碼要用 C 重寫的話, f2c 和 p2c 對(duì)你非常有用。 這兩個(gè)程序產(chǎn)生的 C 代碼一般不用修改就直接能被 GCC 編譯。
如果要轉(zhuǎn)換的 FORTRAN 或 Pascal 程序比較小的話可以直接使用 f2c 或 p2c 不用加任何選項(xiàng)。 如果要轉(zhuǎn)換的程序比較龐大, 包含很多文件的話你可能要用到一些命令行選項(xiàng)。
在
一個(gè) FORTRAN 程序上使用 f2c , 輸入下面的命令:
f2c my_fortranprog.f
注意: f2c 要求被轉(zhuǎn)換的程序的擴(kuò)展名為 .f 或 a .F 。
要把一個(gè)Pascal 程序裝換為 C 程序, 輸入下面的命令:
p2c my_pascalprogram.pas
這兩個(gè)程序產(chǎn)生的 C 源代碼的文件名都和原來的文件名相同, 但擴(kuò)展名由 .f 或 .pas 變?yōu)?.c 。
關(guān)鍵字:程序、文件、 C 編譯器
新文章:
- CentOS7下圖形配置網(wǎng)絡(luò)的方法
- CentOS 7如何添加刪除用戶
- 如何解決centos7雙系統(tǒng)后丟失windows啟動(dòng)項(xiàng)
- CentOS單網(wǎng)卡如何批量添加不同IP段
- CentOS下iconv命令的介紹
- Centos7 SSH密鑰登陸及密碼密鑰雙重驗(yàn)證詳解
- CentOS 7.1添加刪除用戶的方法
- CentOS查找/掃描局域網(wǎng)打印機(jī)IP講解
- CentOS7使用hostapd實(shí)現(xiàn)無AP模式的詳解
- su命令不能切換root的解決方法
- 解決VMware下CentOS7網(wǎng)絡(luò)重啟出錯(cuò)
- 解決Centos7雙系統(tǒng)后丟失windows啟動(dòng)項(xiàng)
- CentOS下如何避免文件覆蓋
- CentOS7和CentOS6系統(tǒng)有什么不同呢
- Centos 6.6默認(rèn)iptable規(guī)則詳解