1、gcc test.c你能用-o编译选项来为将产生的可执行文件指定一个文件名来代替a.out.例如,将一个叫count.c的C程序编译为名叫count的可执行文件,你将输入下面的命令:gcc-o count count.c当你使用-o选项时,-o后面必须跟一个文件名.GCC同样有指定编译器处理多少的编译选项.-c选项告诉GCC仅把源代码编译为目标代码而跳过汇编和连接的步骤.这个选项使用的非常频繁因为它使得编译多个C程序时速度更快并且更易于管理.缺省时GCC建立的目标代码文件有一个.o的扩展名.-S编译选项告诉GCC在为C代码产生了汇编语言文件后停止编译.GCC产生的汇编语言文件的缺省扩展名是.s
2、.-E选项指示编译器仅对输入文件进行预处理.当这个选项被使用时,预处理器的输出被送到标准输出而不是储存在文件里.优化选项当你用GCC编译C代码时,它会试着用最少的时间完成编译并且使编译后的代码易于调试.易于调试意味着编译后的代码与源代码有同样的执行次序,编译后的代码没有经过优化.有很多选项可用于告诉GCC在耗费更多编译时间和牺牲易调试性的基础上产生更小更快的可执行文件.这些选项中最典型的是-O和-O2选项.-O选项告诉GCC对源代码进行基本优化.这些优化在大多数情况下都会使程序执行的更快.-O2选项告诉GCC产生尽可能小和尽可能快的代码.-O2选项将使编译的速度比使用-O时慢.但通常产生的代码
3、执行速度会更快.除了-O和-O2优化选项外,还有一些低级选项用于产生更快的代码.这些选项非常的特殊,而且最好只有当你完全理解这些选项将会对编译后的代码产生什么样的效果时再去使用.这些选项的详细描述,请参考GCC的指南页,在命令行上键入man gcc.调试和剖析选项GCC支持数种调试和剖析选项.在这些选项里你会最常用到的是-g和-pg选项.-g选项告诉GCC产生能被GNU调试器使用的调试信息以便调试你的程序.GCC提供了一个很多其他C编译器里没有的特性,在GCC里你能使-g和-O(产生优化代码)联用.这一点非常有用因为你能在与最终产品尽可能相近的情况下调试你的代码.在你同时使用这两个选项时你必须
4、清楚你所写的某些代码已经在优化时被GCC作了改动.关于调试C程序的更多信息请看下一节用gdb调试C程序.-pg选项告诉GCC在你的程序里加入额外的代码,执行时,产生gprof用的剖析信息以显示你的程序的耗时情况.关于gprof的更多信息请参考gprof一节.用gdb调试GCC程序Linux包含了一个叫gdb的GNU调试程序.gdb是一个用来调试C和C+程序的强力调试器.它使你能在程序运行时观察程序的内部结构和内存的使用情况.以下是gdb所提供的一些功能:它使你能监视你程序中变量的值.它使你能设置断点以使程序在指定的代码行上停止执行.它使你能一行行的执行你的代码.在命令行上键入gdb并按回车键就
5、可以运行gdb了,如果一切正常的话,gdb将被启动并且你将在屏幕上看到类似的内容:GDB is free software and you are welcome to distribute copies of it under certain conditions;typeshow copyingto see the conditions.There is absolutely no warranty for GDB;show warrantyfor details.GDB 4.14(i486-slakware-linux),Copyright 1995 Free Software Foun
6、dation,Inc.(gdb)当你启动gdb后,你能在命令行上指定很多的选项.你也可以以下面的方式来运行gdb:gdb fname当你用这种方式运行gdb,你能直接指定想要调试的程序.这将告诉gdb装入名为fname的可执行文件.你也可以用gdb去检查一个因程序异常终止而产生的core文件,或者与一个正在运行的程序相连.你可以参考gdb指南页或在命令行上键入gdb-h得到一个有关这些选项的说明的简单列表.为调试编译代码(Compiling Code for Debugging)为了使gdb正常工作,你必须使你的程序在编译时包含调试信息.调试信息包含你程序里的每个变量的类型和在可执行文件里的地
7、址映射以及源代码的行号.gdb利用这些信息使源代码和机器码相关联.在编译时用-g选项打开调试选项.gdb基本命令gdb支持很多的命令使你能实现不同的功能.这些命令从简单的文件装入到允许你检查所调用的堆栈内容的复杂命令,表27.1列出了你在用gdb调试时会用到的一些命令.想了解gdb的详细使用请参考gdb的指南页.表27.1.基本gdb命令.命令描述file装入想要调试的可执行文件.kill终止正在调试的程序.list列出产生执行文件的源代码的一部分.next执行一行源代码但不进入函数内部.step执行一行源代码而且进入函数内部.run执行当前被调试的程序quit终止gdb watch使你能监视
8、一个变量的值而不管它何时被改变.break在代码里设置断点,这将使程序执行到这里时被挂起.make使你能不退出gdb就可以重新产生可执行文件.shell使你能不离开gdb就执行UNIX shell命令.gdb支持很多与UNIX shell程序一样的命令编辑特征.你能象在bash或tcsh里那样按Tab键让gdb帮你补齐一个唯一的命令,如果不唯一的话gdb会列出所有匹配的命令.你也能用光标键上下翻动历史命令.gdb应用举例本节用一个实例教你一步步的用gdb调试程序.被调试的程序相当的简单,但它展示了gdb的典型应用.下面列出了将被调试的程序.这个程序被称为greeting,它显示一个简单的问候,
9、再用反序将它列出.#include stdio.h main()char my_string=hello there;my_print(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;s
10、tring2size+1=messageThe string printed backward is%sn,string2);用下面的命令编译它:gcc-o test test.c这个程序执行时显示如下结果:The string is hello there The string printed backward is输出的第一行是正确的,但第二行打印出的东西并不是我们所期望的.我们所设想的输出应该是:The string printed backward is ereht olleh由于某些原因,my_print2函数没有正常工作.让我们用gdb看看问题究竟出在哪儿,先键入如下命令:gdb
11、greeting记得在编译greeting程序时把调试选项打开.如果你在输入命令时忘了把要调试的程序作为参数传给gdb,你可以在gdb提示符下用file命令来载入它:(gdb)file greeting这个命令将载入greeting可执行文件就象你在gdb命令行里装入它一样.这时你能用gdb的run命令来运行greeting了.当它在gdb里被运行后结果大约会象这样:(gdb)run Starting program:/root/greeting The string is hello there The string printed backward is Program exited wi
12、th code 041这个输出和在gdb外面运行的结果一样.问题是,为什么反序打印没有工作?为了找出症结所在,我们可以在my_print2函数的for语句后设一个断点,具体的做法是在gdb提示符下键入list命令三次,列出源代码:(gdb)list(gdb)list技巧:在gdb提示符下按回车健将重复上一个命令.第一次键入list命令的输出如下:1#include stdio.h 3main()45 char my_string=7 my_print(my_string);8 my_print2(my_string);910如果按下回车,gdb将再执行一次list命令,给出下列输出:11 my
13、_print(char*string)1213 printf(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;24 string2size-i=stringi;25 string2size+1=message26 printf(27根据列出的源程序,你能看到要设断点的地方在第24行,在gdb命令行提示符下键入如下命令设置断点:(gdb
14、)break 24 gdb将作出如下的响应:Breakpoint 1at 0x139:file greeting.c,line 24(gdb)现在再键入run命令,将产生如下的输出:Starting program:/root/greeting The string is hello there Breakpoint 1,my_print2(string=0xbfffdc4)at greeting.c:24 24 string2size-i=stringi你能通过设置一个观察string2size-i变量的值的观察点来看出错误是怎样产生的,做法是键入:(gdb)watch string2siz
15、e-igdb将作出如下回应:Watchpoint 2:string2size-i现在可以用next命令来一步步的执行for循环了:(gdb)next经过第一次循环后,gdb告诉我们string2size-i的值是h.gdb用如下的显示来告诉你这个信息:Watchpoint 2,string2size-iOld value=0message0New value=104hmy_print2(string=0xbfffdc423 23 for(i=0;i+)这个值正是期望的.后来的数次循环的结果都是正确的.当i=10时,表达式string2size-i的值等于e,size-i的值等于1,最后一个字符
16、已经拷到新串里了.如果你再把循环执行下去,你会看到已经没有值分配给string20了,而它是新串的第一个字符,因为malloc函数在分配内存时把它们初始化为空(null)字符.所以string2的第一个字符是空字符.这解释了为什么在打印string2时没有任何输出了.现在找出了问题出在哪里,修正这个错误是很容易的.你得把代码里写入string2的第一个字符的的偏移量改为size-1而不是size.这是因为string2的大小为12,但起始偏移量是0,串内的字符从偏移量0到偏移量10,偏移量11为空字符保留.为了使代码正常工作有很多种修改办法.一种是另设一个比串的实际大小小1的变量.这是这种解决
17、办法的代码:my_print(char*string)my_print2(char*string)int size,size2,i;size2=size-1;string2size2-i=stringi;string2size=message另外的C编程工具Slackware Linux的发行版中还包括一些我们尚未提到的C开发工具.本节将介绍这些工具和它们的典型用法.xxgdb xxgdb是gdb的一个基于X Window系统的图形界面.xxgdb包括了命令行版的gdb上的所有特性.xxgdb使你能通过按按钮来执行常用的命令.设置了断点的地方也用图形来显示.你能在一个Xterm窗口里键入下面的
18、命令来运行它:xxgdb你能用gdb里任何有效的命令行选项来初始化xxgdb.此外xxgdb也有一些特有的命令行选项,表27.2列出了这些选项.表27.2.xxgdb命令行选项.描述db_name指定所用调试器的名字,缺省是gdb.db_prompt指定调试器提示符,缺省为gdb.gdbinit指定初始化gdb的命令文件的文件名,缺省为.gdbinit.nx告诉xxgdb不执行.gdbinit文件.bigicon使用大图标.calls你可以在sunsite.unc.edu FTP站点用下面的路径:/pub/Linux/devel/lang/c/calls.tar.Z来取得calls,一些旧版本
19、的Linux CD-ROM发行版里也附带有.因为它是一个有用的工具,我们在这里也介绍一下.如果你觉得有用的话,从BBS,FTP,或另一张CD-ROM上弄一个拷贝.calls调用GCC的预处理器来处理给出的源程序文件,然后输出这些文件的里的函数调用树图.在你的系统上安装calls,以超级用户身份登录后执行下面的步骤:1.解压和untar文件.2.cd进入calls untar后建立的子目录.3.把名叫calls的文件移动到/usr/bin目录.4.把名叫calls.1的文件移动到目录/usr/man/man1.5.删除/tmp/calls目录.这些步骤将把calls程序和它的指南页安装载你的系统
20、上.当calls打印出调用跟踪结果时,它在函数后面用中括号给出了函数所在文件的文件名:maintest.c如果函数并不是向calls给出的文件里的,calls不知道所调用的函数来自哪里,则只显示函数的名字:printf calls不对递归和静态函数输出.递归函数显示成下面的样子:fact recursive in factorial.c静态函数象这样显示:totalstatic in calculate.c作为一个例子,假设用calls处理下面的程序:将产生如下的输出:1 maintest.c2 my_printtest.c3 printf 4my_print2test.c5 strlen 6
21、malloc 7printfcalls有很多命令行选项来设置不同的输出格式,有关这些选项的更多信息请参考calls的指南页.方法是在命令行上键入calls-h.cproto cproto读入C源程序文件并自动为每个函数产生原型申明.用cproto可以在写程序时为你节省大量用来定义函数原型的时间.如果你让cproto处理下面的代码:,*string);你将得到下面的输出:/*test.c*/int main(void);int my_print(char*string);int my_print2(char*string);这个输出可以重定向到一个定义函数原型的包含文件里.indent indent实用程序是Linux里包含的另一个编程实用工具.这个工具简单的说就为你的代码产生美观的缩进的格式.indent也有很多选项来指定如何格式化你的源代码.这些选项的更多信息请看indent的指南页,在命令行上键入indent-h.下面的例子是indent的缺省输出:运行indent以前的C代码:#include stdio.h main()my_print2(char*string),strin
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1