主讲:油海东院系:信息学院通信教研室302专业:通信07,信工07,电信07,计本07嵌入式系统设计与开发第3章LINUX下的C编程基础1.Linux下C语言编程概述2.LINUX下C语言编辑器的使用3.GCC编译器的使用4.Gdb调试器的使用C语言回顾•BELL实验室、DennisRitchie在B语言的基础上发展起来的。•87年,ANSI美国国家标准协会,制定了ANSIC标准,规范了与硬件的无关性•C语言是中级语言•C语言是结构化的语言•C语言是功能强大的语言•C语言是可移植性很强的语言LINUX下C语言编程环境源代码*.c预处理器编译器汇编处理目标代码*.o链接可执行文件引导代码头文件库函数编辑器•类似于WINDOWS下的记事本,完成程序文本的录入工作,LINUX下常用的编辑器有Vi,Emacs编译链接器•源代码生成可执行代码的过程•编译链接过程非常复杂–词法、语法、语义分析–中间代码的生成和优化–符号表的管理–出错处理•Linux下常用的编译器是GCC编译器调试器•方便程序员调试程序的工具•LINUX下常用的调试器Gdb项目管理器•类似与VC中的“工程”,对源代码进行合理有效的组织•LINUX下的项目管理器是Make第5章LINUX下的C编程基础1.Linux下C语言编程概述2.LINUX下C语言编辑器的使用3.GCC编译器的使用4.Gdb调试器的使用启动vi•建立一个名字为test.txt文件,使用命令行启动vi•[root@testroot]#vitest.txtVi启动画面Vi的模式•Vi的模式有三种:一般模式、编辑模式、命令模式•一般模式:–以vi处理一个文件的时候,一进入该档案就是一般模式了。–在这个模式中,可以使用“上下左右”按键来移动光标,您可以使用“删除字符”或“删除整行”来处理档案内容,也可以使用“复制、粘贴”来处理文件数据。Vi的模式•编辑模式:•在一般模式中可以处理删除、复制、贴上等动作,但是却无法编辑。按下“i,I,o,O,a,A,r,R”字母之后才会进入编辑模式。•注意:在Linux中,按下上述的字母时,在画面的左下方会出现“INSERT或REPLACE”的字样,才可以输入文本•按下“Esc”键即可退出编辑模式,回到一般模式。Vi的模式•命令模式:•在一般模式当中,输入“:或/“就可以将光标移动到最底下那一行。•在这个模式当中,可以提供您”搜寻资料“的动作,而读取、存盘、大量取代字符、离开vi、显示行号等等的动作则是在此模式中实现的。模式转换图例子•1.Vitest.txt。启动vi,进入一般模式例子•2.按下i,进入编辑模式,开始输入文字例子•3.按下[ESC]按钮回到一般模式;•编辑完毕后,按下[Esc]键,回到一般模式画面左下角的–INSERT–消失。例子•4.在一般模式中按下“:wq”储存后离开vi!命令内容说明命令内容说明命令内容说明命令内容说明命令内容说明命令内容说明第5章LINUX下的C编程基础1.Linux下C语言编程概述2.LINUX下C语言编辑器的使用3.GCC编译器的使用4.Gdb调试器的使用什么是GCC•早期:GCC-GNUCComplier•现在:GCC-GNUComplierCollection•GNU推出的功能强大、优秀的跨平台编译器•支持主流的CPU平台,完成从源程序向特定CPU硬件平台上目标代码的转换。GCC所支持的源程序后缀说明.cC源程序.aLINUX/UNIX库文件.c;.gcc;.cxxC++源程序.h头文件.i预处理后的C文件.ii预处理后的C++文件.o编译后的目标文件.s汇编程序.S预编译后的汇编程序GCC工具链•GCC是一组编译工具的总称,包括–C编译器:cc,ccl,cclplus,gccgcc++编译器:c++,cclplus,g++–源码预处理器:cpp,cpp0–库文件:libgcc.a,libgcc_eh.a,libgcc_s.so,libiberty.a,libstdc++.[a,so],libsupc++.aGCC工作过程•GCC将C源程序、C++源程序、汇编程序等编译、链接成可执行程序,分为4步:•预处理(Pre-processing):调用cpp命令,分析源代码中的各种伪指令,如#include,#define•编译(Compiling):预处理结束,调用ccl命令进行编译,将预处理后的源代码解释为汇编语言•汇编(Assembling):调用as命令,把汇编程序会变成目标代码•链接(Linking):调用ld命令,把目标代码按照链接规则(链接脚本)链接起来,形成可执行文件,链接过程中,可使用系统中的标准函数、函数库链接是个什么过程?可执行文件•GCC经过上述4步,最终形成可执行程序,可执行文件没有统一的后缀名。•根据文件属性来区分该文件是否能被执行。•默认可执行文件为.elf(executivelinkedfile)格式,elf格式由若干段(section)组成,如果没有特别指明,由标准c源代码生成的目标文件中包含以下段:.text(正文段)包含程序的指令代码,.data(数据段)包含固定的数据,如常量,字符串等,.bss(未初始化数据段)包含未初始化的变量和数组等。•如果GCC编译时没有明确给出输出文件名,则系统自动生成一个a.out的可执行文件。GCC的用法•GCC是linux/UNIX下基于命令行的编译器。•语法:gcc[选项]要编译的文件[选项][目标文件],目标文件可以缺省,默认生成的可执行文件命名为:编译文件.out•options:编译时需要的选项(100个可用),–总体选项–告警选项–优化选项–体系结构相关选项–选项由-和字母组成,如-c、-o等。GCC总体选项列表选项名含义-c只是编译,不链接;生成目标文件.o-S只是编译,不汇编,生成汇编代码-E只进行预编辑,不进行其它处理-g在可执行程序中包含标准调试信息-ofile把输出文件输出到file-v输出GCC的版本信息-Idir在头文件的搜索路径列表中添加dir目录-Ldir在库文件的搜索路径列表中添加dir目录-static链接静态函数库-llibrary链接名字为library的库文件告警和出错选项列表选项含义-ansi支持符合ANSI标准的C程序-pedantic允许发出ANSIC标准所列出的全部警告信息-error允许发出ANSIC标准所列出的全部错误信息-w关闭所有告警-Wall允许发出GCC提供的所有有用的报警信息-werror把所有的告警信息转换为错误信息,并在有告警时,终止编译过程体系结构相关选项选项含义-mcpu=type针对不同的CPU,使用相应的指令。可选的type有i386/i486/i686/pentium等-mieee-fp使用IEEE标准进行浮点数的比较-mno-ieee-fp不使用IEEE标准进行浮点数的比较-msoft-float输出包含浮点库调用的目标代码-mshort把int类型作为16位处理,相当于shortintGCC常用编译选项-1•-c:对源程序进行预处理、编译、汇编,生成目标文件(.o),并不链接生成可执行程序。常用于编译子程序。gcc–ctest1.c,生成test1.o•-ooutput_filename:指明输出的可执行文件的名称。在没有指明编译选项时,生成a.out可执行文件。gcc–otesttest.c,生成可执行文件testgcctest.c,生成可执行文件a.outGCC常用编译选项-2•-g:如果需要对源代码进行调试,必须使用该参数,这时gcc为gdb调试工具加入必要的调试信息•-O:在编译、链接过程中对源代码进行优化,付出的代价是编译、链接过程较慢。•-O2:比-O更好的优化编译、链接。•-S:生成一个后缀为.s的汇编文件•-E:对源代码只进行预处理,预处理结果送到标准输出。•-v:输出GCC的版本信息GCC常用编译选项-3•-IDIR:将DIR指定的目录加入到程序头文件目录列表中。预编译过程中使用。默认头文件路径:/usr/include/头文件不在上述目录下,使用该选项gcc–I/home/include–otesttest1.c•-LDIR:将DIR指定的目录加入到程序函数档案库文件目录列表中。链接过程中使用。默认库文件路径:/usr/lib/gcc–L/home/zxq/lib–lapp–otesttest1.c,链接使用liblap库。Linux下库文件均以lib开头GCC常用编译选项-4•-lname:连接时,装载名字为libname.a的函数库。gccfile1.cfile2.c–lm–ofile,整个程序由file1和file2构成,连接时使用到了libm.a函数库,使用-o选项生成可执行文件file•作为交叉开发工具使用时,需要根据具体使用的cpu类型,使用具体的GCC编译器,如使用ARM,在gcc编译时,使用如下指令:arm-elf-gcc–g–ofilefile.c错误及告警选项•-w:禁止输出告警信息•-Werror:将所有告警转换为错误•-Wall:显示所有告警信息GCC的错误类型及对策•C语法错误,错误信息:syntexerror•头文件错误,错误信息:cannotfindincludefile…,头文件名错、指定头文件所在目录错,和””用法错•档案库错,错误信息:NosuchfileorDirectory,函数库名错,指定函数库所在目录错。•未定义符号,错误信息:Undefinedsymbol举例•1.使用vi编辑器编写C源程序如下#includestdio.hintmain(){printf(hello!thisisourembededworld!\n);return0;}举例•2.预处理阶段gcc–Ehello.c–ohello.i,得到预处理后的C源程序,以下为hello.i文件的部分内容。把stdio.h中内容插入到了hello.i举例•3.编译阶段:检查代码有无语法错误,检查无误后,把代码翻译成汇编语言,使用-S选项查看,该选项只编译,不汇编。gcc–Shello.i–ohello.s以下为hello.s的部分内容举例•4.汇编阶段:把编译阶段生成的汇编程序.s转成目标文件,使用-c选项,可以把汇编程序转换成2进制代码.ogcc–chello.s–ohello.o,以下为hello.o的部分内容举例•5.链接阶段:有个重要概念:函数库。程序中没有定义printf函数,stdio.h中也只是printf的声明,printf在哪里呢?事实上,该函数的实现在名字为libc.so.6的库文件当中,该库文件在/usr/lib目录下,没有特别指定,gcc会自动到该目录下搜索库文件。该库是动态库。gcchello.o–ohello运行生成的可执行文件./hello,注意,执行该文件时,应指明该文件的目录“./”,为什么?得到结果hello!,thisisourembededworld!观看视频GCC的使用直接生成可执行程序•在使用GCC时,不必一定要按照以上几步一一来做,有了源程序之后,如果源程序没有错误,使用GCC,一步就可以生成可执行程序•gcchello.c–ohello出错信息选项•如下程序#includestdio.hvoidmain(){longlongtmp=1;printf(“thisisabadcode!\n”);return0;}该程序有哪些错误?使用-ansi选项编译有问题程序•该选项强制GCC生成标准语法所要求的告警信息gcc–ansiwarning.c–owarning警告信息如下:warning.c:在函数main中:warning.c:7警告:在无返回值的函数中,“return”带返回值warning.c:4警告:“main”的返回类型不是int没有发现longlong这个无效的数据类型。使用-pedantic选项gcc–pedanticwarning.c–owarning告警信息如下:war