GCC编程与开发总结报告.docx
- 文档编号:23732428
- 上传时间:2023-05-20
- 格式:DOCX
- 页数:25
- 大小:692.29KB
GCC编程与开发总结报告.docx
《GCC编程与开发总结报告.docx》由会员分享,可在线阅读,更多相关《GCC编程与开发总结报告.docx(25页珍藏版)》请在冰豆网上搜索。
GCC编程与开发总结报告
Gcc编程与开发总结报告
姓名:
学号:
学院:
2010年12月
Gcc编程与开发总结报告
一、Gcc简介:
GCC(GNUCompilerCollection),是一套由GNU开发的编程语言编译器。
除了编译程序之外,它还含其他相关工具,所以它能把易于人类使用的高级语言编写的源代码构建成计算机能够直接执行的二进制代码。
GCC是Linux平台下最常用的编译程序,它是Linux平台编译器的事实标准。
同时,在Linux平台下的嵌入式开发领域,GCC也是用得最普遍的一种编译器。
GCC之所以被广泛采用,是因为它能支持各种不同的目标体系结构。
例如,它既支持基于宿主的开发(简单讲就是要为某平台编译程序,就在该平台上编译),也支持交叉编译(即在A平台上编译的程序是供平台B使用的)。
目前,GCC支持的体系结构有四十余种,常见的有X86系列、Arm、PowerPC等。
同时,GCC还能运行在不同的操作系统上,如Linux、Solaris、Windows等。
除了上面讲的之外,GCC除了支持C语言外,还支持多种其他语言,例如C++、Ada、Java、Objective-C、FORTRAN、Pascal等。
二、Gcc开发技术:
1、GCC基本规则:
.c为后缀的文件,C语言源代码文件;
.C、.cc或.cxx为后缀的文件,是C++源代码文件;
.a为后缀的文件,是由目标文件构成的档案库文件;
.h为后缀的文件,是程序所包含的头文件;
.i为后缀的文件,是已经预处理过的C源代码文件;
.ii为后缀的文件,是已经预处理过的C++源代码文件;
.m为后缀的文件,是Objective-C源代码文件;
.o为后缀的文件,是编译后的目标文件;
.s为后缀的文件,是汇编语言源代码文件;
.S为后缀的文件,是经过预编译的汇编语言源代码文件。
2、Gcc的应用方法:
1)Gcc的编译过程:
在使用GCC编译程序时,过程可以被分为四个阶段:
◆预处理(Pre-Processing),生成.i文件【预处理器cpp】
◆编译(Compiling),将预处理后的文件不转换成汇编语言,生成.s文件【编译器egcs】
◆汇编(Assembling),由汇编变成目标代码(机器代码)生成.o文件【汇编器as】
◆链接(Linking),连接目标代码,生成可执行程序【链接器ld】
Linux程序员可以根据自己的需要让Gcc在编译的任何阶段结束,以便检查或使用编译器在该阶段的输出信息,或者对最后生成的二进制文件进行控制,以便通过加入不同数量和种类的调试代码来为今后的调试做好准备。
和其它常用的编译器一样,Gcc也提供了灵活而强大的代码优化功能,利用它可以生成执行效率更高的代码。
2)Gcc最基本的用法和常用选项
Gcc命令的基本用法是∶gcc[options][filenames],其中options就是编译器所需要的参数,filenames给出相关的文件名称。
-c,只编译,不连接成为可执行文件,编译器只是由输入的.c等源代码文件生成.o为后缀的目标文件,通常用于编译不包含主程序的子程序文件。
-o,output_filename,确定输出文件的名称为output_filename,同时这个名称不能和源文件同名。
如果不给出这个选项,gcc就给出预设的可执行文件a.out。
-g,产生符号调试工具(GNU的gdb)所必要的符号资讯,要想对源代码进行调试,我们就必须加入这个选项。
-O,对程序进行优化编译、连接,采用这个选项,整个源代码会在编译、连接过程中进行优化处理,这样产生的可执行文件的执行效率可以提高,但是,编译、连接的速度就相应地要慢一些。
-O2,比-O更好的优化编译、连接,当然整个编译、连接过程会更慢。
-Idirname,将dirname所指出的目录加入到程序头文件目录列表中,是在预编译过程中使用的参数。
3)C程序中的头文件包含两种情况∶
A)#include
B)#include“myinc.h”
其中,A类使用尖括号(<>),B类使用双引号(“”)。
对于A类,预处理程序cpp在系统预设包含文件目录(如/usr/include)中搜寻相应的文件,而对于B类,cpp在当前目录中搜寻头文件,这个选项的作用是告诉cpp,如果在当前目录中没有找到需要的文件,就到指定的dirname目录中去寻找。
在程序设计中,如果我们需要的这种包含文件分别分布在不同的目录中,就需要逐个使用-I选项给出搜索路径。
-Ldirname,将dirname所指出的目录加入到程序函数档案库文件的目录列表中,是在连接过程中使用的参数。
在预设状态下,连接程序ld在系统的预设路径中(如/usr/lib)寻找所需要的档案库文件,这个选项告诉连接程序,首先到-L指定的目录中去寻找,然后到系统预设路径中寻找,如果函数库存放在多个目录下,就需要依次使用这个选项,给出相应的存放目录。
-lname,在连接时,装载名字为“libname.a”的函数库,该函数库位于系统预设的目录或者由-L选项确定的目录下。
例如,-lm表示连接名为“libm.a”的数学函数库。
上面我们简要介绍了gcc编译器最常用的功能和主要参数选项,更为详尽的资料可以参看Linux系统的联机帮助。
假定我们有一个程序名为test.c的C语言源代码文件,要生成一个可执行文件,最简单的办法就是∶
gcctest.c
这时,预编译、编译连接一次完成,生成一个系统预设的名为a.out的可执行文件,对于稍为复杂的情况,比如有多个源代码文件、需要连接档案库或者有其他比较特别的要求,就要给定适当的调用选项参数。
再看一个简单的例子。
整个源代码程序由两个文件testmain.c和testsub.c组成,程序中使用了系统提供的数学库,同时希望给出的可执行文件为test,这时的编译命令可以是∶
gcctestmain.ctestsub.c□lm□otest
其中,-lm表示连接系统的数学库libm.a。
4)Gcc编程实例
首先我们通过gedit命令编写一个简单的C程序,代码如下:
#include"stdio.h"
main()
{
inti,j,result;
printf("\n");
for(i=1;i<10;i++)
{
for(j=1;j<10;j++)
{
result=i*j;
printf("%d*%d=%-3d",i,j,result);/*-3d表示左对齐,占3位*/
}
printf("\n");/*每一行后换行*/
}
}
将该程序保存为fun1.c文件,然后在终端输入命令来对其进行编译和运行该段程序,我们通过命令:
gcc–ofun1fun1.c将编译后生成的目标文件命名为fun1,如果直接执行命令:
gccfun1.c,则编译后生成默认的可执行文件a.out,编译通过的文件通过列表后则显示成绿色的可执行文件名。
最后执行命令语句:
./fun1,则是运行当前文件,得到如下的结果:
3、Make命令的使用和Makefile文件的编写
在Linux环境中,make是一个非常重要的编译命令。
不管是自己进行项目开发还是安装应用软件,用户都会经常用到make或makeinstall命令。
利用make工具,可以将大型的开发项目分解成为多个更易于管理的模块分别开发。
对于一个包括几百个源文件的应用程序,使用make和makefile工具就可以省去每次都要键入gcc命令进行编译的麻烦而自动完成编译,大大提高项目开发的效率。
ØMakefile文件的编写
假设我们有下面这样的一个程序,源代码如下:
/*main.c*/
#include"app1.h"
#include"app2.h"
intmain()
{
app1print();
app2print();
return0;
}
/*app1.h*/
#ifndef_APP_1_H
#define_APP_1_H
voidapp1print();
#endif
/*app1.c*/
#include"app1.h"
#include"stdio.h"
voidapp1print()
{
printf("Thisisapp1print\n");
}
/*app2.h*/
#ifndef_APP_2_H
#define_APP_2_H
voidapp2print();
#endif
/*app2.c*/
#include"app2.h"
#include"stdio.h"
voidapp2print()
{
printf("Inapp2,first,callapp1:
");
app1print();
printf("Thisisapp2print\n");
}
从上面的源代码可以清晰的看到,app1.h和app2.h中定义了两个功能的函数,分别是app1print()和app2print();其中app2.h中的功能函数调用了app1.h中的app1print()函数。
当然由于这个程序是很短的我们可以这样来编译
gcc-cmain.c
gcc-capp1.c
gcc-capp2.c
gcc-omainmain.oapp1.oapp2.o
这样的话我们也可以产生main程序,而且也不是很麻烦。
但是如果我们考虑一下如果有一天我们修改了其中的一个文件(比如说app1.c)那么我们难道还要重新输入上面的命令?
也许你会说,这个很容易解决啊,我写一个SHELL脚本,让她帮我去完成不就可以了。
是的对于这个程序来说,是可以起到作用的.但是当我们把事情想的更复杂一点,如果我们的程序有几百个源程序的时候,难道也要编译器重新一个一个的去编译?
为此,聪明的程序员们想出了一个很好的工具来做这件事情,这就是make。
我们只要执行以下make,就可以把上面的问题解决掉。
在我们执行make之前,我们要先编写一个非常重要的文件—Makefile。
其编写流程是:
(1)编写可执行文件生成规则
该程序要生成的可执行文件的名称是myapp,则要生成此可执行文件所需要的3个object文件分别是main.o、app1.o、app2.o,即myapp依赖于这三个文件。
第一步的编写规则是:
myapp:
main.oapp1.oapp2.o
(TAB)gcc–omyappmain.oapp1.oapp2.o
(2)编写各目标文件生成规则
●main.o文件:
main.o:
main.capp1.happ2.h
(TAB)gcc–cmain.c
●app1.o文件:
app1.o:
app1.capp1.h
(TAB)gcc–capp1.c
●app2.o文件:
app2.o:
app2.capp1.happ2.h
(TAB)gcc–capp2.c
(3)编写伪目标规则
一般要在后面定义一个伪目标:
clean。
它的生成规则为:
clean:
(TAB)$(RM)*.omyapp
(4)PHONY的应用
当输入makeclean时,由于伪目标规则中没有依赖文件,而且clean文件总是最新的,因此按照Makefile文件的运行规则,rm*.omyapp是不会i被执行的。
这显然是有问题的。
为解决这个问题,要用到.PHONY,使用这个字符串可显示指定clean为伪目标,而不将其视为文件。
./PHONY的格式为:
./PHONY:
clean
将上述规则合并在一起,便得到所需要的Makefile文件
有了这个Makefile文件,不过我们什么时候修改了源程序当中的什么文件,我们只要执行make命令,我们的编译器都只会去编译和我们修改的文件有关的文件。
ØMakefile的基本语法规则:
在Makefile中#开始的行都是注释行,Makefile中最重要的是描述文件的依赖关系的说明,其基本规则是由目标文件、依赖文件和响应命令三部分组成的,它的一般格式是:
–target...:
prerequisites...//依赖关系
–target:
要生成的目标文件
–prerequisites:
target所依赖的文件
–command:
make所要执行的命令(任意的shell命令)
Makefile有三个非常有用的变量。
分别是$@,$^,$<代表的意义分别是:
$@--目标文件,$^--所有的依赖文件,$<--第一个依赖文件。
如果我们使用上面三个变量,那么我们可以简化我们的Makefile文件为:
#这是简化后的Makefile
main:
main.oapp1.oapp2.o
gcc-o$@$^
main.o:
main.capp1.happ2.h
gcc-c$<
app1.o:
app1.capp1.h
gcc-c$<
app2.o:
app2.capp2.h
gcc-c$<
经过简化后我们的Makefile是简单了一点,不过人们有时候还想简单一点。
这里我们学习一个Makefile的缺省规则
.c.o:
gcc-c$<
这个规则表示所有的.o文件都是依赖与相应的.c文件的。
例如app.o依赖于app.c这样Makefile还可以变为:
#这是再一次简化后的Makefile
main:
main.oapp1.oapp2.o
gcc-o$@$^
.c.o:
gcc-c$<
ØMake命令的使用
使用make管理器非常简单,只需要在make命令的后面键入目标名即可建立指定的目标,如果直接运行make,则建立Makefile中的第一个目标。
●make的命令格式:
–make[-fmakefile][option]...target...
●make的一些常用命令选项
-p表示打印出Makefile中所有宏定义和描述内部规则的相关行
-i忽略执行中所遇到的所有错误
-k在错误发生后尽可能的继续执行
-d打印调试信息
-s执行而不显示执行状况
-n打印出要执行的命令,但是并不执行这些命令,可以用来检查Makefile正确性
●Make的工作步骤
-读入所有的Makefile
-读入被include的其它Makefile
-初始化文件中的变量
-推导隐含规则,并分析所有规则
-为所有的目标文件创建依赖关系链
-根据依赖关系,决定哪些目标要重新生成
-执行生成命令。
●输入make命令后,若有错误,可以根据错误的提示,进行相应的修改。
例如上述程序在输入make命令后出现:
makefile:
4:
***missingseparator.Stop.这种错误的原因在于gcc这一命令行前面应该用tab键,而不能用空格。
修改之后再执行make命令,正确生成了目标文件和可执行文件,证明Makefile文件编写正确。
4、Stock应用的Makefile文件详细分析
PROGS=stock//目标名字保存在变量PROGS中
all:
$(PROGS)//使用PROGS这个变量
CC=g++//CC变量被设置为g++
OBJS=main.omenu.odata.omisc.odraw.o\
stkfile.ocheckhis.ochecknow.o\
jszb.ochoicestock.o\
showhqwin.otblman.o\
keys.ocalculator.o\
areatotal.odataman.osystem.o\
cfgfile.otcp_client.o\
tcp_ip_ruleset.ostocksql.o\
stockclient.oconnect.o
CFLAGS=-Wall-O-I.\
-I/usr/X11R6/include\
-I/usr/lib/glib/include\
-I/usr/X11R6/include/X11
LIBS=-L.-L/usr/lib\
-L/usr/local/lib/mysql\
-L/usr/X11R6/lib\
-lgtk-lgdk-rdynamic\
-lgmodule-lglib-ldl-lXext-lX11-lm\
-lmysqlclient
//声明了3个变量
.c.o:
$(CC)$(CFLAGS)-c$<
//所有的.o文件都是依赖于.c文件的
stock:
$(OBJS)
$(CC)-o$@$(OBJS)$(LIBS)
//执行OBJS和LIBS定义的文件中所有的命令
main.o:
gmclient.h
menu.o:
gmclient.h
data.o:
gmclient.hjszb.hstocksql.h
misc.o:
gmclient.h
draw.o:
gmclient.hdraw.hstocksql.hjszb.h
stkfile.o:
gmclient.hjszb.hstocksql.h
checkhis.o:
gmclient.h
checknow.o:
gmclient.h
jszb.o:
gmclient.hjszb.h
choicestock.o:
gmclient.h
showhqwin.o:
gmclient.h
tblman.o:
gmclient.h
keys.o:
gmclient.hjszb.h
calculator.o:
gmclient.h
areatotal.o:
gmclient.h
dataman.o:
gmclient.h
system.o:
gmclient.hstocksql.h
cfgfile.o:
gmclient.h
tcp_client.c:
tcp_client.htcp_ip_ruleset.h
stocksql.c:
gmclient.hstocksql.hjszb.h
stockclient.c:
gmclient.hstockclient.h
connect.c:
gmclient.hstockclient.hstocktype.h
冒号前边是target(目标文件),冒号后面是依赖文件。
实质就是目标文件由依赖文件生成。
5、调试器Gdb的主要功能和使用方法
在程序编译通过生成可执行文件之后,就进入了程序的调试环节。
调试一直以来是程序开发的重中之重,如何使程序员能够迅速找到错误的原因是一款调试器的目标。
GDB是GUN开源组织发布的一个强大的Linux下的程序调试工具,它是一种强大的命令行调试工具。
(1)Gdb的主要功能
●能够运行程序,设置所有能影响程序运行的参数。
●能够让程序在指定的条件下停止。
●能够在程序停止时检查所有参数的情况。
●能够根据指定条件改变程序的运行。
(2)Gdb的调试方法
下面通过一个简单的实例介绍GDB的使用方法,首先编写一个C程序:
#include"stdio.h"
/*子函数是add,将自然数1~m想加*/
main()
{
inti,n=0;
add(50);
for(i=1;i<=50;i++)
n+=i;
printf("Thesumof1-50is%d\n",n);
}
add(intm)
{
inti,n=0;
for(i=1;i<=m;i++)
n+=i;
printf("Thesumof1-%dinaddis%d\n",m,n);
printf("i=%d\n",i);
}
●注意:
使用GDB进行调试之前,需要在编译时加上“-g”选项才能使目标可执行文件包含可被调试的信息,即使用命令:
gcc–ofun3fun3.c–g//编译并连接程序,使之包含可被调试信息
gdbfun//使用GDB调试器打开fun3可执行文件
完成以上操作后,系统将显示GDB调试器的版本、使用的函数库信息,并显示(gdb)命令提示符。
这时可输入命令对程序进行调试,常用的命令如下:
1.l(list)列出程序清单
2.r(run)运行程序
3.b(breakpoint)设置断点,格式:
b[行号/函数名]
4.bnumifi==20设置断点的触发条件
5.condition断点号i==50改变断点的触发条件
6.infob查看断点信息
7.clear[行号],清除断点
8.c(continue)继续运行程序
9.s(step)单步运行,stepinto
10.n(next)单步运行,stepover
11.finish跳出函数,stepout
12.print变量/表达式,显示变量或表达式的值
13.display变量/表达式,每次程序停止运行时都显示变量或表达式的值
●查看文件
在gdb提示符下键入list命令三次,列出源代码:
(gdb)list
(gdb)list
(gdb)list
技巧:
在gdb提示符下按回车健将重复上一个命令。
输出效果如下:
可以看出,GDB列出的源代码中明确的给出了对应的行号,这样可以大大方便代码的定位。
●设置断点并查看断点处的情况
在gdb中设置断点非常简单,只需在“b”后加入对应的行号即可,其命令如下:
(gdb)b1//设置断点1
Breakpoint1at0x8048328:
filefun3.c,line1.
(gdb)infob//给出断点的信息
NumTypeDispEnbAddressWhat
1breakpointkeepy0x08048328inaddatfun3.c:
1
(gdb)r
Startingprogram:
/root/task/fun3
Breakpoint1,add(m=1)atfun3.c:
4
4{
(gdb)b6//设置断点2
Breakpoint2at0x8048335:
filefun3.c,line6.
(gdb)infob//给出断点的信息
NumTypeDispEnbAddressWhat
1breakpointkeepy0x08048328inaddatfun3.c:
1
breakpointalreadyhit1time
2breakpointkeepy0x08048335inaddatfun3.c:
6
查看变量值-观察变量-单步运行-退出GDB
(gdb)pi//查看变量i的值
$1=107382870
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- GCC 编程 开发 总结报告