ImageVerifierCode 换一换
格式:DOCX , 页数:12 ,大小:27.23KB ,
资源ID:3646260      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/3646260.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(gcc教程.docx)为本站会员(b****6)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

gcc教程.docx

1、gcc教程一 :不经意间,GCC已发展到了4.3的版本,尽管在软件开发社区之外乏人闻问,但因为GCC在几乎所有开源软件和自由软件中都会用到,因此它的编译性能的涨 落会直接影响到Linux 、Firefox 乃至于OpenOffice.org和Apache等几千个项目的开发。因此,把GCC摆在开源软件的核心地位是一点也不为过。另一方面,GCC4.3的 出现,正在牵引着广大程序员们的心。如果我们非要用一个词来说明GCC与程序员之间的关系,那无疑是心随心动。历史篇作为自由软件的旗舰项目,Richard Stallman 在十多年前刚开始写作 GCC 的时候,还只是把它当作仅仅一个 C 程序语言的编译

2、器;GCC 的意思也只是 GNU C Compiler 而已。经过了这么多年 的发展,GCC 已经不仅仅能支持 C 语言;它现在还支持Ada 语言、C+ 语言、Java 语言、Objective C 语言、Pascal 语言、COBOL语言,以及支持函数式编程和逻辑编程的 Mercury 语言,等等。而 GCC 也不再单只是 GNU C 语言编译器的意思了,而是变成了 GNU Compiler Collection 也即是 GNU 编译器家族的意思了。另一方面,说到 GCC 对于各种硬件平台的支持,概括起来就是一句话:无所不在。几乎所有有点实际用途的硬件平台,甚至包括有些不那么有实际用途的硬件

3、平台。Gcc 简介Linux系统下的gcc(GNU C Compiler)是GNU推出的功能强大、性能优越的多平台编译器,是GNU的代表作品之一。Gcc是可以在多种硬体平台上编译出可执行程序的超级编译器,其执行效率与一般的编译器相比平均效率要高20%30%。官方网站:http:/gcc.gnu.org/ gcc是linux的唯一编译器,没有gcc就没有linux,gcc的重要性就不可言喻啦。居然这么重要,那就很值得我们来好好研究下啦。好啦,开始我们的gcc之旅吧!首先消除gcc和g+误区吧。gcc和g+都是GNU(组织)的一个编译器。误区一:gcc只能编译c代码,g+只能编译c+代码两者都可以

4、,但是请注意:1.后缀为.c的,gcc把它当作是C程序,而g+当作是c+程序;后缀为.cpp的,两者都会认为是c+程序,注意,虽然c+是c的超集,但是两者对语法的要求是有区别的,例如:#include int main(int argc, char* argv) if(argv = 0) return;printString(argv);return;int printString(char* string) sprintf(string, This is a test.n);如果按照C的语法规则,OK,没问题,但是,一旦把后缀改为cpp,立刻报三个错:“printString未定义”;“ca

5、nnot convert char* to char*”;”return-statement with no value“;分别对应前面红色标注的部分。可见C+的语法规则更加严谨一些。2.编译阶段,g+会调用gcc,对于c+代码,两者是等价的,但是因为gcc命令不能自动和C程序使用的库联接,所以通常用g+来完成链接,为了统一起见,干脆编译/链接统统用g+了,这就给人一种错觉,好像cpp程序只能用g+似的。误区二:gcc不会定义_cplusplus宏,而g+会实际上,这个宏只是标志着编译器将会把代码按C还是C+语法来解释,如上所述,如果后缀为.c,并且采用gcc编译器,则该宏就是未定义的,否则,

6、就是已定义。误区三:编译只能用gcc,链接只能用g+严格来说,这句话不算错误,但是它混淆了概念,应该这样说:编译可以用gcc/g+,而链接可以用g+或者gcc -lstdc+。因为gcc命令不能自动和C程序使用的库联接,所以通常使用g+来完成联接。但在编译阶段,g+会自动调用gcc,二者等价。误区四:extern C与gcc/g+有关系实际上并无关系,无论是gcc还是g+,用extern c时,都是以C的命名方式来为symbol命名,否则,都以c+方式命名。试验如下:me.h: extern C void CppPrintf(void); me.cpp:#include #include me

7、.husing namespace std;void CppPrintf(void)cout Hellon;test.cpp:#include #include #include me.h int main(void)CppPrintf();return 0;1. 先给me.h加上extern C,看用gcc和g+命名有什么不同rootroot G+# g+ -S me.cpprootroot G+# less me.s.globl _Z9CppPrintfv /注意此函数的命名.type CppPrintf, functionrootroot GCC# gcc -S me.cpprootro

8、ot GCC# less me.s.globl _Z9CppPrintfv /注意此函数的命名.type CppPrintf, function完全相同!2. 去掉me.h中extern C,看用gcc和g+命名有什么不同rootroot GCC# gcc -S me.cpprootroot GCC# less me.s.globl _Z9CppPrintfv /注意此函数的命名.type _Z9CppPrintfv, functionrootroot G+# g+ -S me.cpprootroot G+# less me.s.globl _Z9CppPrintfv /注意此函数的命名.ty

9、pe _Z9CppPrintfv, function完全相同!【结论】完全相同,可见extern C与采用gcc/g+并无关系,以上的试验还间接的印证了前面的说法:在编译阶段,g+是调用gcc的。二:今天,我们继续gcc之旅吧。上节我们讲了些gcc的历史发展什么的,还有就是gcc与g+的区别。今天我们就从整体上对gcc编译过程有个细致的了解,也好明白他的工作原理,好为以后深入学习研究打下个基础。gcc的编译流程分为四个步骤,分别为: 预处理(Pre-Processing) 编译(Compiling) 汇编(Assembling) 链接(Linking)以hello.c为例子,在这四个步骤中可以

10、设置选项分别生成hello.i, hello.s, hello.o以及最终的hello文件:hello.c : 最初的源代码文件;hello.i : 经过编译预处理的源代码;hello.s : 汇编处理后的汇编代码;hello.o : 编译后的目标文件,即含有最终编译出的机器码,但它里面所引用的其他文件中函数的内存位置尚未定义。hello / a.out : 最终的可执行文件(还有.a(静态库文件), .so(动态库文件), .s(汇编源文件)留待以后讨论) 下面就具体来查看一下gcc是如何完成四个步骤的。hello.c源代码#includeint main()printf(Hello Wor

11、ld!n);return 0;(1)预处理阶段在该阶段,编译器将上述代码中的stdio.h编译进来,并且用户可以使用gcc的选项”-E”进行查看,该选项的作用是让gcc在预处理结束后停止编译过程。深入理解计算机系统中是这么说的:预处理器(cpp)根据以字符#开头的命令(directives),修改原始的C程序。如hello.c中#include 指令告诉预处理器读系统头文件stdio.h的内容,并把它直接插入到程序文本中去。结果就得到另外一个C程序,通常是 以.i作为文件扩展名的。注意:Gcc指令的一般格式为:Gcc 选项 要编译的文件 选项 目标文件其中,目标文件可缺省,Gcc默认生成可执行

12、的文件名为:编译文件.outganlocalhost gcc# gcc E hello.c o hello.i选项”-o”是指目标文件,”.i”文件为已经过预处理的C原始程序。以下列出了hello.i文件的部分内容:typedef int (*_gconv_trans_fct) (struct _gconv_step *,struct _gconv_step_data *, void *,_const unsigned char *,_const unsigned char *,_const unsigned char *, unsigned char *,size_t *);# 2 hell

13、o.c 2int main()printf(Hello World!n);return 0;由此可见,gcc确实进行了预处理,它把”stdio.h”的内容插入到hello.i文件中。(2)编译阶段接 下来进行的是编译阶段,在这个阶段中,Gcc首先要检查代码的规范性、是否有语法错误等,以确定代码的实际要做的工作,在检查无误后,Gcc把代码翻译成 汇编语言。用户可以使用”-S”选项来进行查看,该选项只进行编译而不进行汇编,生成汇编代码。汇编语言是非常有用的,它为不同高级语言不同编译器提供了 通用的语言。如:C编译器和Fortran编译器产生的输出文件用的都是一样的汇编语言。ganlocalhost

14、 gcc# gcc S hello.i o hello.s以下列出了hello.s的内容,可见Gcc已经将其转化为汇编了,感兴趣的读者可以分析一下这一行简单的C语言小程序是如何用汇编代码实现的。.file hello.c.section .rodata.align 4.LC0:.string Hello World!.text.globl main.type main, functionmain:pushl %ebpmovl %esp, %ebpsubl $8, %espandl $-16, %espmovl $0, %eaxaddl $15, %eaxaddl $15, %eaxshrl $

15、4, %eaxsall $4, %eax subl %eax, %espsubl $12, %esppushl $.LC0 call putsaddl $16, %espmovl $0, %eaxleaveret.size main, .-main.ident GCC: (GNU) 4.0.0 20050519 (Red Hat 4.0.0-8).section .note.GNU-stack,progbits(3)汇编阶段汇编阶段是把编译阶段生成的”.s”文件转成目标文件,读者在此可使用选项”-c”就可看到汇编代码已转化为”.o”的二进制目标代码了。如下所示:ganlocalhost gcc

16、# gcc c hello.s o hello.o(4)链接阶段在成功编译之后,就进入了链接阶段。在这里涉及到一个重要的概念:函数库。在这个源程序中并没有定义”printf”的函数实现,且在预编译中包含进的”stdio.h”中也只有该函数的声明,而没有定 义函数的实现,那么,是在哪里实现”printf”函数的呢?最后的答案是:系统把这些函数实现都被做到名为libc.so.6的库文件中去了,在没有特 别指定时,gcc会到系统默认的搜索路径”/usr/lib”下进行查找,也就是链接到libc.so.6库函数中去,这样就能实现函数”printf” 了,而这也就是链接的作用。函数库一般分为静态库和动态

17、库两种。静态库是指编译链接时,把库文件的代码全部加入到可执行文件中, 因此生成 的文件比较大,但在运行时也就不再需要库文件了。其后缀名一般为”.a”。动态库与之相反,在编译链接时并没有把库文件的代码加入到可执行文件中,而是在 程序执行时由运行时链接文件加载库,这样可以节省系统的开销。动态库一般后缀名为”.so”,如前面所述的libc.so.6就是动态库。gcc在编译时 默认使用动态库。(Linux下动态库文件的扩展名为.so(Shared Object)。按照约定,所有动态库文件名的形式是libname.so(可能在名字中加入版本号)。这样,线程函数库被称作 libthread.so。静态库的

18、文件名形式是libname.a。共享archive的文件名形式是libname.sa。共享archive只是一 种过渡形式,帮助人们从静态库转变到动态库。)完成了链接之后,gcc就可以生成可执行文件,如下所示。ganlocalhost gcc# gcc hello.o o hello运行该可执行文件,出现正确的结果如下。rootlocalhost Gcc# ./helloHello World!三:这一节,我们来关注下gcc的常用参数 ,有机会也好多加练习啦。 首先来看看我们gcc的版本吧,gcc -version这个命令就会显示gcc的版本号啦 。好啦,下面开始下面开始讲解gcc的常用参数啦

19、o(_)o.参数详解-c 只激活预处理,编译,和汇编,也就是他只把程序做成obj文件例子用法:gcc -c hello.c他将生成.o的obj文件 -S只激活预处理和编译,就是指把文件编译成为汇编代码。例子用法gcc -S hello.c他将生成.s的汇编代码,你可以用文本编辑器察看-E只激活预处理,这个不生成文件,你需要把它重定向到一个输出文件里面.例子用法:gcc -E hello.c pianoapan.txtgcc -E hello.c | more慢慢看吧,一个hello word 也要与处理成800行的代码-o制定目标名称,缺省的时候,gcc 编译出来的文件是a.out,很难听,如

20、果 你和我有同感,改掉它,哈哈例子用法gcc -o hello.exe hello.c (哦,windows用习惯了)gcc -o hello.asm -S hello.c-ansi关闭gnu c中与ansi c不兼容的特性,激活ansi c的专有特性(包括禁止一些asm inline typeof关键字,以及UNIX,vax等预处理宏,-Wall显示警告信息-O0-O1-O2-O3编译器的优化选项的4个级别,-O0表示没有优化,-O1为缺省值,-O3优化级别最高-g只是编译器,在编译的时候,产生调试信息。-llibrary 制定编译的时候使用的库例子用法gcc -lcurses hello.

21、c使用ncurses库编译程序-Ldir制定编译的时候,搜索库的路径。比如你自己的库,可以用它制定目录,不然编译器将只在标准库的目录找。这个dir就是目录的名称。 -gstabs此选项以stabs格式声称调试信息,但是不包括gdb调试信息. -gstabs+此选项以stabs格式声称调试信息,并且包含仅供gdb使用的额外调试信息.-ggdb此选项将尽可能的生成gdb的可以使用的调试信息.-static 此选项将禁止使用动态库,所以,编译出来的东西,一般都很大,也不需要什么 动态连接库,就可以运行.-share 此选项将尽量使用动态库,所以生成文件比较小,但是需要系统由动态库.-traditio

22、nal 试图让编译器支持传统的C语言特性-fno-asm此选项实现ansi选项的功能的一部分,它禁止将asm,inline和typeof用作关键字。-fno-strict-prototype只对g+起作用,使用这个选项,g+将对不带参数的函数,都认为是没有显式的对参数的个数和类型说明,而不是没有参数.而gcc无论是否使用这个参数,都将对没有带参数的函数,认为城没有显式说明的类型-fthis-is-varialble就是向传统c+看齐,可以使用this当一般变量使用.-fcond-mismatch允许条件表达式的第二和第三参数类型不匹配,表达式的值将为void类型-funsigned-char-

23、fno-signed-char-fsigned-char-fno-unsigned-char这四个参数是对char类型进行设置,决定将char类型设置成unsigned char(前两个参数)或者 signed char(后两个参数)-include file包含某个代码,简单来说,就是便以某个文件,需要另一个文件的时候,就可以用它设定,功能就相当于在代码中使用#include例子用法:gcc hello.c -include /root/pianopan.h-imacros file将file文件的宏,扩展到gcc/g+的输入文件,宏定义本身并不出现在输入文件中-Dmacro相当于C语言中的

24、#define macro-Dmacro=defn相当于C语言中的#define macro=defn-Umacro相当于C语言中的#undef macro-undef取消对任何非标准宏的定义 -Idir在你是用#includefile的时候,gcc/g+会先在当前目录查找你所制定的头文件,如果没有找到,他回到缺省的头文件目录找,如果使用-I制定了目录,他回先在你所制定的目录查找,然后再按常规的顺序去找.对于#include,gcc/g+会到-I制定的目录查找,查找不到,然后将到系统的缺省的头文件目录查找-I-就是取消前一个参数的功能,所以一般在-Idir之后使用-idirafter dir在

25、-I的目录里面查找失败,讲到这个目录里面查找.-iprefix prefix-iwithprefix dir一般一起使用,当-I的目录查找失败,会到prefix+dir下查找-nostdinc使编译器不再系统缺省的头文件目录里面找头文件,一般和-I联合使用,明确限定头文件的位置-nostdin C+规定不在g+指定的标准路经中搜索,但仍在其他路径中搜索,.此选项在创建libg+库使用-C在预处理的时候,不删除注释信息,一般和-E使用,有时候分析程序,用这个很方便的 -M生成文件关联的信息。包含目标文件所依赖的所有源代码你可以用gcc -M hello.c来测试一下,很简单。 -MM和上面的那个

26、一样,但是它将忽略由#include造成的依赖关系。 -MD和-M相同,但是输出将导入到.d的文件里面-MMD和-MM相同,但是输出将导入到.d的文件里面-Wa,option此选项传递option给汇编程序;如果option中间有逗号,就将option分成多个选项,然后传递给会汇编程序-Wl.option此选项传递option给连接程序;如果option中间有逗号,就将option分成多个选 项,然后传递给会连接程序.-x language filename 设定文件所使用的语言,使后缀名无效,对以后的多个有效.也就是根据约定C语言的后缀名称是.c的,而C+的后缀名是.C或者.cpp,如果你很

27、个性, 决定你的C代码文件的后缀名是.pig 哈哈,那你就要用这个参数,这个参数对他后面的文件名都起作用,除非到了下一个参数的使用。 可以使用的参数吗有下面的这些 c, objective-c, c-header, c+, cpp-output, assembler, and assembler-with-cpp. 看到英文,应该可以理解的。 例子用法: gcc -x c hello.pig-x none filename 关掉上一个选项,也就是让gcc根据文件名后缀,自动识别文件类型 例子用法: gcc -x c hello.pig -x none hello2.c-pipe 使用管道代替编

28、译中临时文件,在使用非gnu汇编工具的时候,可能有些问题 gcc -pipe -o hello.exe hello.c-funsigned-char -fno-signed-char -fsigned-char -fno-unsigned-char 这四个参数是对char类型进行设置,决定将char类型设置成unsigned char(前两个参 数)或者 signed char(后两个参数)GCC的参数是很多的,这也只是部分。不过对于初学者来说,一时之间掌握这么 多的参数也是有点困难的,不过一般推荐使用命令:gcc -Wall hello.c -o hello 就足够啦。一般要使用-Wall这

29、个参数,他可以列出源程序在编译过程中出现的错误警告等信息,这是很有帮助的,注意:-Wall这个参数是在编译过程中 使用的,若先把源程序编译成目标文件,则在链接过程中不要使用这个参数。你还可以再加个 -v参数:列出比较详细的信息,(在标准错误)显示执行编译阶段的命令.同时显示编译器驱动程序,预处理器,编译器的版本号.这些在我们平时使用的过程中应该已经足够啦,若还想了解其他的一些参数,可以下载gcc的帮助文档有时间自己研究下。四 :多文件编译、连接如果原文件分布于多个文件中:file1.c, file2,c$ gcc -Wall file1.c file2.c -o name若对其中一个文件作了修

30、改,则可只重新编译该文件,再连接所有文件:$ gcc -Wall -c file2.c$ gcc file1.c file2.o -c name注意:有些编译器对命令行中的.o文件的出现顺序有限制:含有某函数定义的文件必须出现在含有调用该函数的文件之后。好在GCC无此限制。编译预处理在程序中包含与连接库对应的头文件是很重要的方面,要使用库,就一定要能正确地引用头文件。一般在代码中通过#include引入头文件, 如果头文件位于系统默认的包含路径(/usr/includes), 则只需在#include中给出头文件的名字, 不需指定完整路径. 但若要包含的头文件位于系统默认包含路径之外, 则有其它的工作要做: 可以(在源文件中)同时指定头文件的全路径. 但考虑到可移植性,最好通过-I在调用gcc的编译命令中指定。下面看这个求

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1