C语言-GCC基础培训.ppt_第1页
C语言-GCC基础培训.ppt_第2页
C语言-GCC基础培训.ppt_第3页
C语言-GCC基础培训.ppt_第4页
C语言-GCC基础培训.ppt_第5页
已阅读5页,还剩72页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1,C语言-GCC,上海*通信技术有限公司Jim(seniordba)2011-05,2,培训大纲,一、gcc简介二、gcc编译过程三、gcc编译选项四、静态/动态链接库五、其它,3,gcc简介,名称:GNUprojectCandC+CompilerGNUCompilerCollectiongcc是一个全功能的ANSIC兼容编译器,它是所有UNIX系统可用的C编译器。gcc是可以在多种硬体平台上编译出可执行程序的超级编译器,其执行效率与一般的编译器相比平均效率要高20%30%。,4,查看版本信息,5,查看安装路径,6,相关文件类型,c为后缀的文件,C语言源代码文件;.a为后缀的文件,是由目标文件构成的档案库文件;.C,.cc或.cxx为后缀的文件,是C+源代码文件;.h为后缀的文件,是程序所包含的头文件;.i为后缀的文件,是已经预处理过的C源代码文件;.ii为后缀的文件,是已经预处理过的C+源代码文件;.m为后缀的文件,是Objective-C源代码文件;.o为后缀的文件,是编译后的目标文件;.s为后缀的文件,是汇编语言源代码文件;.S为后缀的文件,是经过预编译的汇编语言源代码文件。,7,gcc编译的4个过程,预处理(也称预编译,Preprocessing):命令gcc首先调用cpp进行预处理,在预处理过程中,对源代码文件中的文件包含(include)、预编译语句(如宏定义define等)进行分析。编译(Compilation):接着调用cc1进行编译,这个阶段根据输入文件生成以.o为后缀的目标文件。汇编(Assembly):汇编过程是针对汇编语言的步骤,调用as进行工作。连接(Linking):当所有的目标文件都生成之后,gcc就调用ld来完成最后的关键性工作,这个阶段就是连接,8,可执行程序的生成过程,预处理(Preprocessing):分析各种预处理命令,如#define,#include,#if等;编译(Compilation):根据输入文件产生汇编语言的程序;汇编(Assembly):将汇编语言输入,产生扩展名为.o的目标文件;链接(Linking):以.o目标文件,库文件作为输入,生成可执行文件;,源程序文件(.h,.c),经预处理的文件(.i),汇编语言文件(.s),目标文件(.o),可执行程序(.out),9,培训大纲,一、gcc简介二、gcc编译过程三、gcc编译选项四、静态/动态链接库五、其它,10,GCC编译过程,典型的编译过程test.c预处理test.i编译test.s汇编test.o连接test$cattest.c(查看程序源代码)#includeintmain(intargc,char*argv)printf(helloworldn);return0;$gccotesttest.c(编译连接程序)$./test(执行test程序),11,1、没有任何选项:gcchelloworld.c结果会在和helloworld.c相同的目录下产生一个a.out的可执行文档。2、-o选项,指定输出文档名:gcc-ohelloworldhelloworld.c-o意思是Output即需要指定输出的可执行文档的名称。这里的名称为helloworld。3、-c选项,只编译汇编,不连接:gcc-chelloworld.c-c意思就是Compile,产生一个叫helloworld.o的目标文档4、-S选项,产生汇编源文档:gcc-Shelloworld.c-S意思就是aSsemble,产生一个叫helloworld.s的汇编源文档5、-E选项,预处理C源文档:gcc-Ehelloworld.c-E意思就是prEprocess。输出不是送到一个文档而是标准输出。当然能够对他进行重定向:gcc-Ehelloworld.chelloworld.txt,12,预处理,预编译命令:$gcc-otest.i-Etest.c或者$cpp-otest.itest.c这里cpp不是值cplusplus,而是theCPreprocessor执行结果:生成预处理后的文件test.i,该文件包含了test.c需要的所有的类型和函数申明。原理:读取c源程序,对伪指令和特殊符号进行处理。包括宏,条件编译,包含的头文件,以及一些特殊符号。基本上是一个替换的过程。,13,#define用法,#include#defineAA100intmain(void)AABBprintf(“hellon”);预处理命令gccEhello.cDBB=hellogccEhello.cDBB=“printf(”hello”);”gccEhello.cDBB(等效于-DBB=1),注释这一行看看预处理的结果,-D表示在命令行中传入宏定义-DBB=后面是一个宏的定义,可以加双引号。,14,#define带参数,#include#defineAA(a,b)a=bintmain(void)AA(inta,1);printf(“hellon”);预处理命令gccEhello.c,展开就成了:inta=1;AA宏带两个参数,15,#define带参数,#include#ifdefAAaa#elifdefinedBBbb#elifdefinedCCcc#elseother#endifintmain(void)printf(“hellon”);gccEhello.cDAA=1aaintmain(void)printf(“hellon”);,#ifdefAA等效于#ifdefinedAA表示当定义了宏AA,表示除此之外的情况,表示否则定义了宏CC的情况,16,#define带参数,#include#ifAAaa#elifBBbb#elifCCcc#elseother#endifintmain(void)printf(“hellon”);,#ifAA表示AA非零的情况也就是AA除了0其它数字都为真,表示除此之外的情况,#elifBB表示BB非零的情况#elif表示否则如果,17,gccEhello.cDAA=1,aaintmain(void)printf(“hellon”);gccEhello.cDAA=0otherintmain(void)printf(“hellon”);,18,#的用法,在函数式宏定义中,#运算符用于创建字符串,#运算符后面应该跟一个形参(中间可以有空格或Tab),例如:#defineSTR(s)#schar*p=STR(helloworld)结果变成:char*p=“helloworld”,19,#的用法,在宏定义中可以用#运算符把前后两个预处理Token连接成一个预处理Token,和#运算符不同,#运算符不仅限于函数式宏定义,变量式宏定义也可以用。例如:#defineFOO(a)foo#ainta=FOO(bar);intb=FOO();预处理之后变成:inta=foobar;intb=foo;,20,预处理头文件xxx.h,#ifndefHEADER_FILENAME#defineHEADER_FILENAME/*bodyofheader*/#endif当xxx.h被多次包含的时候。,21,有三个头文件和一个C文件,common.hfile2.hfile3.hmain.c#ifndef_COMMON_H_#define_COMMON_H_staticinttest(void)printf(“hellon”);#endiffile1.h文件内容如下:#include“common.h”file2.h文件内容如下:#include“common.h”main.c内容如下#include#include“file1.h”#include“file2.h”intmain(void)test();gccomainmain.c,如果没有写上红色部分的,是什么情况。,22,常用的#debug宏定义,intmain()printf(“here%s%s%dn”,_FILE_,_func_,_LINE_);printf(“here%s%s%dn”,_FILE_,_func_,_LINE_);printf(“here%s%s%dn”,_FILE_,_func_,_LINE_);,太多printf不好区分如何打出printf的时候也打出行号,函数,文件之类的信息,23,编译,编译命令:$gcc-otest.s-Stest.i(-S编译选项)$cc1-otest.stest.i(cc1为C语言真正编译器)结果:生成汇编文件test.s,test.s中包含了AT,$gcctest.c$./a.outHelloWorld!或$gcc-otesttest.c$./testHelloWorld!,28,常用选项及含义,29,gcc的常用选项,30,gcc的常用选项,31,gcc的常用选项,32,示例,33,-Wall:允许所有有用的警告(建议总是使用该选项),/*bad.c*/#includeintmain(intargc,char*argv)printf(“Twoplustwois%fn”,4);return0;,例1:$gccbad.cobad例2:$gccWallbad.cobad,33,例1:,34,-o:定义输出文件,例:编译多个源文件$gcc-Wallmain.chello.c-ohelloworld,/*hello.h*/voidhello(constchar*name);,/*hello.c*/#include#includehello.hvoidhello(constchar*name)printf(Hello,%s!n,name);,/*main.c*/#includehello.hintmain(intargc,char*argv)hello(world);return0;,34,例2:,35,-l:链接外部库文件,库是已经编译好并能被链接入程序的对象文件的集合。库中提供一些最常用的系统函数,比如象C的数学库中求平方根函数sqrt。,库通常被存储在扩展名为“.a”或“.so”的特殊归档文件中。,C标准库自身存放在“/usr/lib/libc.a”中,包含ANSI/ISOC标准指定的各个函数,是默认自动加载的库。,/*sqrt.c*/#include#includeintmain(intargc,char*argv)doubler=sqrt(3.0);printf(Thesquarerootof3.0is%fn,r);return0;,例:$gcc-Wallsqrt.c-osqrt,ccbR6Ojm.o:Infunctionmain:ccbR6Ojm.o(.text+0 x19):undefinedreferencetosqrt,35,例:,36,-l:链接外部库文件,函数sqrt()并不定义在源程序中或默认的C库“libc.a”中。,为了使得编译器能把sqrt()函数链接到主程序“sqrt.c”,需要提供“libm.a”库。,例:$gcc-Wallsqrt.c/usr/lib/libm.a-osqrt,/usr/lib/libm.a,-lm,$gcc-Wallsqrt.c-lm-osqrt,编译器选项“-lNAME”试图链接标准库目录下的文件名为“libNAME.a”中的对象文件,36,例:,37,函数库的链接次序,原则:包含函数定义的库应该出现在任何使用到该函数的源文件和对象文件之后,例1:$gcc-Wall-lmsqrt.c-osqrt(incorrect)$gcc-Wallsqrt.c-lm-osqrt(correct),例2:$gcc-Wallsqrt.c-lglpk-lm-osqrt,程序“sqrt.c”用到了GNULinearProgramming库“libglpk.a”,而该库又依次用到数学库“libm.a”,那么应当这么编译:,37,例:,38,-L:设置库文件的搜索路径,如果链接时用到的库不在gcc用到的标准库目录中,就会报这样的错。,/usr/local/lib/usr/lib/,例:$gcc-Wall-L/tmp/libsqrt.c-lm-osqrt,-L/tmp/lib,38,例:,39,-I:设置头文件的搜索路径,如果头文件不在gcc用到的标准include文件路径中,就会报这样的错。,/usr/local/include/usr/include/,例:$gcc-Wall-I/tmp/includesqrt.c-lm-osqrt,-I/tmp/include,39,例:,40,生成预处理文件,命令-E选项使得gcc生成预处理文件后停止。$gccEhello.cohello.i,预处理文件hello.i的部分内容.externvoidfunlockfile(FILE*_stream);#679/usr/include/stdio.h3#2hello.c2intmain(void)printf(hellogcc!n);return0;,41,生成汇编文件,命令$gccShello.cohello.s,汇编文件hello.s的部分内容.main:pushl%ebpmovl%esp,%ebp.addl$16,%espmovl$0,%eaxleaveret.,42,生成二进制文件,生成目标文件命令:$gccchello.cohello.o生成可执行文件命令:$gcchello.cohello运行程序$./hellohellogcc!,43,培训大纲,一、gcc简介二、gcc编译过程三、gcc编译选项四、静态/动态链接库五、其它,44,静态库与动态库,创建函数库分类:静态库:在编译过程中将库函数代码直接加入到生成的可执行程序中,程序运行过程中不需要利用库函数。共享库:编译时,只是在生成的可执行程序中简单指定需要使用的库函数信息,程序运行过程中需要利用库函数。动态库:共享库的一种变化形式,目前大都采用共享库的方式。命名:静态库:前缀lib+库名+.a(libm.a,libstdc+.a等)共享库:前缀lib+库名+.so+.版本号(libm.so.6,libc.so.6),45,创建静态库,静态函数库是一组目标文件(*.o)的集合创建步骤:gcc-ctest1.ctest2.c(生成test1.o,test2.o)ar-crlibtest.atest1.otest2.o(生成函数库libtest.a)ar函数说明:用途:创建和修改库函数,或从库函数提取目标文件举例:ar-rslib-namelist-of-files(将列表中的目标文件加入到库中,并产生索引文件)ar-dslib-namelist-of-files(将列表中列出的目标文件从库中删除,并产生索引文件)ar-xlib-namelist-of-files(不修改库文件,从库中提取列表中列出的目标文件),46,创建静态库示例源码,创建静态库的方法:ar,caculation.c#includeintmain(void)intx=5;inty=3;printf(x+y=%3dn,add(x,y);printf(x-y=%3dn,minus(x,y);printf(x*y=%3dn,multiply(x,y);printf(x%y=%3dn,mod(x,y);return1;,add_minus.cintadd(intx,inty)intresult;result=x+y;returnresult;intminus(intx,inty)intresult;result=x-y;returnresult;,multiply_mod.cintmultiply(intx,inty)intresult;result=x*y;returnresult;intmod(intx,inty)intresult;result=x%y;returnresult;,47,创建静态库示例操作命令,48,一个容易忽略的顺序问题,静态库不能先于原程序链接,这是因为开始时还没有任何未定义的符号,库中的内容不会被链入,所以应该注意将静态库的使用(-l选项)都写在最后。,49,创建、使用共享库示例,vicknec$gcc-fPIC-cadd_minus.cvicknec$gcc-fpic-cmultiply_mod.cvicknec$gcc-shared-fpic-olibalg.soadd_minus.omultiply_mod.ovicknec$gcc-ocacul-lalgcaculation.c/usr/bin/ld:cannotfind-lalgcollect2:ldreturned1exitstatusvicknec$gcc-ocacul-L.-lalgcaculation.cvicknec$./cacul./cacul:errorwhileloadingsharedlibraries:libalg.so:cannotopensharedobjectfile:Nosuchfileordirectory,50,创建共享库步骤,创建共享库gcc-c-fPICtest1.cgcc-c-fPICtest2.cgcc-shared-fPIC-olibtest.sotest1.otest2.o编译使用了共享库的程序gcc-omainLdir-ltestmain.c,51,共享库系统自动动态加载问题,1.拷贝动态库文件到/lib或/usr/lib去$cplibalg.so/usr/libor$cplibalg.so/lib2.改变环境变量LD_LIBRARY_PATH$LD_LIBRARY_PATH=$PWD$exportLD_LIBRARY_PATH,52,应用程序自身完成动态加载,可以在自己的程序中使用dlopen()。该函数将打开一个新库,并把它装入内存。dlopen()在dlfcn.h中定义,并在dl库中实现。,53,应用程序自身完成动态加载示例,#include#includeintmain(void)intx=5;inty=3;void*handle;int(*dl_add)(int,int);int(*dl_mod)(int,int);,handle=dlopen(/usr/lib/libalg.so,RTLD_LAZY);dl_add=dlsym(handle,add);dl_mod=dlsym(handle,mod);printf(x+y=%3dn,dl_add(x,y);printf(x%y=%3dn,dl_mod(x,y);dlclose(handle);return1;,54,检查库依赖关系,函数库之间的相互引用ldd的使用:用于查看库函数之间的依赖性vicknecgcc-lab$cd/usr/libvickneclib$lddlibtiff.solibjpeg.so.62=/usr/lib/libjpeg.so.62(0 x4004c000)libz.so.1=/usr/lib/libz.so.1(0 x4006b000)libc.so.6=/lib/i686/libc.so.6(0 x40079000)/lib/ld-linux.so.2=/lib/ld-linux.so.2(0 x80000000),55,动态库路径搜索的先后顺序,编译目标代码时指定的动态库搜索路径;环境变量LD_LIBRARY_PATH指定的动态库搜索路径;配置文件/etc/ld.so.conf中指定的动态库搜索路径;默认的动态库搜索路径/lib;默认的动态库搜索路径/usr/lib.,56,总结:动态共享库的好处,1.动态共享库是共享的,节省了物理开销。2.库版本更新容易,运行时调用,库更新后不用重新链接。3.允许用户在运行时再确定调用哪个库。使得在程序中添加或者删除一个模块时,都不需要在编译时指定库。注意,如果动态共享库无法加载,可能是路径的问题,或是依赖的问题。,57,培训大纲,一、gcc简介二、gcc编译过程三、gcc编译选项四、静态/动态链接库五、其它,58,GNUC扩展简介,gcc使用longlong数据类型提供64位存储单元。内联函数:要求内联函数足够短小,使得能够在代码中展开,同时编译器检查函数类型。要使用-O选项。-finline-functions.使用attribute关键字指明代码相关信息方便优化。gcc对case做了扩展。case语句可以对应一个范围,在case关键字后列出范围的两个边界值,用“空格省略号空格”分隔。,59,多个文件的C程序,为了方便代码重用,通常将主函数和其他函数放在不同文件中的方法。每个函数都有函数声明(函数头)和函数实现(函数体)两部分组成。函数头一般放在头文件中(*.h)中,而函数的定义文件放在实现文件(*.c、*.cpp)中,60,编译多个文件,61,假设3个文件保存在同一个目录下面,如果还使用:命令:$gccmy_y_app会编译通过吗?,62,编译多个文件,目录结构(1)编译命令$gccmy_y_app目录结构(2)编译方式(1)$gccmy_app.cfunctions/y_app-Ifunctions,63,编译多个文件,目录结构(2)编译方式(2)分步编译命令:1、$gcc-cmy_app.c-Ifunctions2、$gcc-cfunctions/greeting.c3、$gccmy_app.ogreeting.oomy_app思路:编译每一个.c文件,得到.o的目标文件;将每一个.o的目标文件链接成一个可执行的文件;,64,aroption,optioncCreateafileoptiondDeleteafilefromthearchiveoptionpPrintalistoffilesinthearchiveoptionqAppendfilestothearchiveoptionrInsertnewfilesinthearchivebyreplacingifafilealreadyexistsinthearchiveoptiontDisplayingcontentsofanarchiveoptionxExtractingfilesfromanarchive,65,ranlibUtility,The“ranlib”commandisusedtocreateindexentriesinsideanarchivefile.示例:$ranlibstatic-lib-name等价于$arsstatic-lib-name,66,nmUtility,usedtolistsymbolsusedinanobjectfile.示例:$nm-slibcommon.a$nm-sa.out另外:aoptionwiththenmcommandalsoshowsthedebugsymbols.,67,objdumpUtility,-fDisplayingHeaderInformation-hDisplayingSectionHeaders-dDisassemblingaFile-aDisplayingInformationaboutLibraryFiles,68,sizeUtility,Thesizeutilitydisplayssizesofeachsectioninanobjectfile.示例:rootboota#sizea.outtextdatabssdechexfilename10152322412714f7a.out,69,lddUtility,Thelddutilityisveryusefulinfindingoutthedependenciesofanexecutableonsharedlibraries.示例:rootboota#ldda.outlibc.so.6=/lib/i686/libc.so.6(0 x4002c000)/lib/ld-linux.so.2=/lib/ld-linux.so.2(0 x40000000)rootboota#,70,建立自己的GCC编译环境,一个系统上如何同时存在并使用多个版本的GCC编译器?建立目标目录:在gcc源代码同一级目录下(与源目录$srcdir是同级目录)%mkdirgcc-build%cdgcc-build配置环境:%./gcc-3.4.0/configure-prefix=/usr/local/gcc-3.4.0-enable-threads=posix-disable-checking-enable-long-long-host=i386-redhat-linux-with-system-zlib-enable-languages=c,c+,java将GCC安装在/usr/local/gcc-3.4.0目录下,支持C/C+和JAVA语言,71,编译安装:%make&makeinstall其它配置:GCC3.4.0的所有文件,包括命令文件(如gcc、g+)、库文件等都在$destdir目录下分别存放,如命令文件放在bin目录下、库文件在lib下、头文件在include下等。由于命令文件和库文件所在的目录还没有包含在相应的搜索路径内,所以必须要作适当的设置之后编译器才能顺利地找到并使用它们。用符号连接的方式实现,这样做的好处是我仍然可以使用系统上原来的旧版本的GCC编译器。%ln-s$destdir/bin/gccgcc34库路径的设置:exportLD_

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论