《C语言编程实践》PPT课件.ppt_第1页
《C语言编程实践》PPT课件.ppt_第2页
《C语言编程实践》PPT课件.ppt_第3页
《C语言编程实践》PPT课件.ppt_第4页
《C语言编程实践》PPT课件.ppt_第5页
已阅读5页,还剩88页未读 继续免费阅读

下载本文档

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

文档简介

上章回顾,宏定义特点和注意细节条件编译特点和主要用处文件包含的路径查询规则C语言扩展宏定义的用法,C语言编程实践,第二章,预习检查,异或的运算符是什么宏定义最主要的特点是什么请列举条件编译三大用法在文件包含中和“”有什么区别如何取得整数register中的第五位值,本章结构,指针特性,C语言编程实践,C语言常犯错误,C语言关键词,C语言编程调试,C语言编程要点,位段,位运算,课程目标,了解位运算的实际应用。了解C语言几个重要关键词的特性和他们之间区别熟悉C语言编程要点熟悉C语言常见的语法错误以及解决方法了解如何去定位错误以及解决错误,2C语言编程实践,位运算指针特性C语言关键词C语言几个以混淆的概念C语言编程易犯毛病集合,2.1位运算,按位与运算按位或运算按位异或运算求反运算左移运算右移运算,2.1位运算,位运算符的含义位运算是指进行二进制位的运算。功能:c语言提供对内存单元的二进制位的操作,使得c语言能够编写系统软件.位运算符运算对象只能为整型或字符型数据.各个位运算符号的使用:,2.1.1按位与运算,按位与printf(Inputaintegernumber:);scanf(%d,程序运行情况:Inputaintegernumber:1000result=0 x3程序说明:(0p=p-sizeof(int)。,2.3.2函数指针,数据指针的三个问题C语言中函数名直接对应于函数生成的指令代码在内存中的地址,因此函数名可以直接赋给指向函数的指针;调用函数实际上等同于“调转指令参数传递处理回归位置入栈”,本质上最核心的操作是将函数生成的目标代码的首地址赋给CPU的PC寄存器;因为函数调用的本质是跳转到某一个地址单元的code去执行,所以可以调用一个根本就不存在的函数实体。,2.3.2函数指针,数据指针实例/*定义一个无参数、无返回类型的*/typedefvoid(*lpFunction)();/*函数指针类型*/*定义一个函数指针,指向*/lpFunctionlpReset=(lpFunction)0 xF000FFF0;/*CPU启动后所执行第一条指令的位置*/lpReset();/*调用函数*/,2.3.3数组与动态申请,动态申请内存方式可以用较大的数组替换尽可能的选用数组,数组不能越界访问;如果使用动态申请,则申请后一定要判断是否申请成功了,并且malloc和free应成对出现!,2.4C语言关键词,consttypedef与definedefine与enumstatic,2.4.1const,const-只读说说以下的区别constinta;intconsta;constint*a;int*consta;intconst*aconst;const的优势关键字const的作用是为给读你代码的人传达非常有用的信息防止便利被无意的代码修改,2.4.1const,const-只读说说以下的区别constinta;intconsta;constint*a;int*consta;intconst*aconst;Const的优势关键字const的作用是为给读你代码的人传达非常有用的信息通过给优化器一些附加的信息,使用关键字const也许能产生更紧凑的代码防止便利被无意的代码修改,2.4.2typedef与define,#define预处理指令在编译预处理时进行简单的替换,不作正确性检查不需要再在内存中分配变量空间调试程序无法检查用#define说明的常量用#under指令取消typedef声明一个新的类型名代替已有的类型名在编译时处理的不实际分配内存空间,2.4.2typedef与define,#define实例#defineyour_intint*your_inta,b;结果相当于int*a,b;只是简单的宏替换即int*a;intb;,typedef例子typedefint*your_int;your_inta,b结果/a,b都为指向int的指针即int*a;int*b;,2.4.3define与enum,#enum特点用enum关键字说明的常量由编译程序自动生成,程序员不需要用手工对常量一一赋值。用enum关键字说明常量使程序更清晰易读,因为在定义enum常量的同时也定义了一个枚举类型标识符。在调试程序时通常可以检查枚举常量。需要分配内存来存储常量,2.4.3define与enum,#enum例子enumError_CodeOUT_OF_MEMORY,INSUFFICIENT_DISK_SPACE,LOGIC_ERROR,FILE_NOT_FOUND;,2.4.3define与enum,#enum相对#define的优势使程序更容易维护使程序更易读使程序调试起来更方便,2.4.4static,static的特点本地的全局变量限制变量的作用域设置变量的存储域static的作用在函数体,一个被声明为静态的变量在这一函数被调用过程中维持其值不变。在模块内(但在函数体外),一个被声明为静态的变量可以被模块内所用函数访问,但不能被模块外其它函数访问。在模块内,一个被声明为静态的函数只可被这一模块内的其它函数调用,2.5C语言编程要点,C语言存储空间布局Heap与stackstatic特性应用字符串常量array_name和externintn;intmain()n=20;printf(%dn,n);display();return0;,staticintn;/*定义全局静态变量,自动初始化为0,仅在本文件中可见*/voiddisplay()n+;printf(%dn,n);,结果:文件分别编译通过,但link的时候teststatic1.c中的变量n找不到定义,2.5.3.1全局静态变量,优势不会被其他文件所访问,修改其他文件中可以使用相同名字的变量,不会发生冲突。静态局部变量和普通局部变量的区别static局部变量只被初始化一次,下一次依据上一次结果值;static函数在内存中只有一份,普通函数在每个被调用中维持一份拷贝,2.5.3.2局部静态变量,定义局部变量之前加上关键字static。特征内存中的位置:静态存储区初始化:未经初始化的局部静态变量会被程序自动初始化为0作用域:作用域仍为局部作用域特征局部变量改变为静态变量后是改变了它的存储方式即改变了它的生存期,从原来的栈中存放改为静态存储区。全局变量改变为静态变量后是改变了它的作用域,限制了它的使用范围,存放位置还是在静态存储区中。,2.5.3.3静态函数,定义在函数的返回类型前加上关键字static特性只是在声明他的文件当中可见,不能被其他文件所用优势其他文件中可以定义相同名字的函数,不会发生冲突静态函数不能被其他文件所用,2.5.3.3静态函数,实例分析:,/teststatic2.c,teststatic1.c,voiddisplay();staticvoidstaticdis();intmain()display();staticdis();renturn0;,voiddisplay()staticdis();printf(display()hasbeencalledn);staticvoidstaticdis()printf(staticdis()hasbeencalledn);,结果:文件分别编译通过,但是连接的时候找不到函数staticdis()的定义,2.5.3.4static实例,例:统计次数功能,voidcount();intmain()inti;for(i=1;i=3;i+)count();return0;voidcount()staticnum=0;num+;printf(Ihavebeencalled%d,num,timesn);,结果:Ihavebeencalled1times.Ihavebeencalled2times.Ihavebeencalled3times.,2.5.4array_name和char*p=a;/*运行下面这句后,vc6.0提示的错误为:cannotconvertfromchar(*)5tochar*,,结果:12450441245040abcdabcd,2.5.4array_name和inti,j;a=65535;i=-1;j=a;b=i;printf(unsigned)%u(int)%dn,a,j);printf(int)%d(unsigned)%un,i,b);,结果:(unsigned)65535(int)-1(int)-1(unsigned)65535,2.5.5强制数据类型转换的总结,转换规则,doublefloat高longunsignedintchar,short低,说明:横向箭头表示必须的转换纵向箭头表示当运算符两边的运算数为不同类型时的转换低高形式上改变,数据的实质内容不变高低可能有些数据丢失,2.5.5强制数据类型转换的总结,转换规则把赋值运算符右侧表达式的类型转换为左侧变量的类型转换细节浮点型与整型单、双精度浮点型char型与int型int型与1ong型无符号整数,阶段小节,常见的位运算符有哪些什么是数据指针如何定义一个函数指针const有那些特点,主要应用在哪些方面static主要有几种用法,各自特点是什么C强制数据类型转化要注意哪些方面,2.6C语言编程易犯毛病集合,书写标识符时,忽略了大小写字母的区别忽略了变量的类型,进行了不合法的运算将字符常量与字符串常量混淆忽略了“=”与“=”的区别忘记加分号多加分号输入字符的格式与要求不一致switch语句中漏写break语句忽视了while和do-while语句在细节上的区别定义数组时误用变量,2.6.1书写标识符时,忽略了大小写字母的区别,分析注意:C认为大写字母和小写字母是两个不同的字符,main()inta=5;printf(%d,A);,2.6.2忽略了变量的类型,进行了不合法的运算,分析注意:整型变量a和b可以进行求余运算,而实型变量则不允许进行“求余”运算,main()floata,b;printf(%d,a%b);,2.6.3将字符常量与字符串常量混淆,分析charc;c=a;注意:字符常量是由一对单引号括起来的单个字符字符串常量是一对双引号括起来的字符序列以“”作字符串结束标志,2.6.3将字符常量与字符串常量混淆,分析charc;c=a;注意:字符常量是由一对单引号括起来的单个字符字符串常量是一对双引号括起来的字符序列以“”作字符串结束标志,2.6.4忽略了“=”与“=”的区别,分析if(a=3)a=b;if(a=3)a=b;注意:“=”是赋值运算符“=”是关系运算符,2.6.5忘记加分号,分析,a=1b=2z=x+y;t=z/100;printf(%f,t);,2.6.6多加分号,分析注意:复合语句的花括号后不应再加分号for(I=0;Iy?x:y;return(z);,注意形参应该在函数体外定义局部变量应该在函数体内定义,2.6.13误认为形参值的改变会影响实参的值,语句分析,语句改正,main()intx=3,y=4;swap(x,y);printf(%d,%d,x,y);intswap(intx,inty)intz;z=x;x=y;y=z;,main()intx=3,y=4;int*p1,*p2;p1=,注意实参和形参之间单向传递,2.6.14函数的实参和形参类型不一致,语句分析,错误分析C要求实参与形参的类型一致P1-指针参数P1-整形参数,main()intx=3,y=4;int*P1,*p2;P1=,2.7C语言的调试,如果我运行的程序挂起了,应该怎么办如何检测内存漏洞(leak)调试程序的最好方法是什么怎样调试TSR程序能报告条件失败的程序,2.7.1如果我运行的程序挂起了,应该怎么办,程序挂起的四大原因程序中有死循环;程序运行的时间比所期望的长;程序在等待某些输入信息,并且直到输入正确后才会继续运行;程序设计的目的就是为了延迟一段时间,或者暂停执行。,2.7.1.1死循环,什么死循环有几种情况可以造成死循环分析例子:解决方式增加对应的调试debug信息,/*initializeadoubledimensionarray*/for(a=0;a10;+a)for(b=0;b10;+a)arrayab=0;,2.7.1.2运行时间比期望的时间长,什么时候会出现这种情况该如何消除分析例子:/*AsubroutinetocalculateFibonaccinumbers*/intfib(inti)if(i3)return1;elsereturnfib(i-1)+fib(i-2);解决方式熟悉基本的语法或者算法运算信息,2.7.1.3等待正确的输入,原因是:等待正确的输入信息分析例子:,#includemain()FILE*in=fopen(numbers.dat,r);inttotal=0,n;while(fscanf(in,%d,2.7.2如何检测内存漏洞(leak),什么是内存漏洞动态分配的内存单元不再使用却没有被释放什么情况会容易出现这样的问题忘记释放分配给临时缓冲区的内存空间内存漏洞特点最难检测最危险,2.7.2如何检测内存漏洞(leak),例子分析,voidSayHi(char*name)char*UpName;inta;UpName=malloc(strlen(name)+1);/*Allocatespaceforthename*/for(a=0;astrlen(name);+a)UpNamea=toupper(namea);UpNamea=0;printf(Hello,%sin,UpName);intmain()SayHi(Dave);return(0);,2.7.2如何检测内存漏洞(leak),解决方案小心谨慎地编写程序,充分考虑到内存漏洞的可能性malloc和free要配对使用相应的软件包利用语言的扩展功能,2.7.3调试程序的最好方法是什么,调试过程的三个要素应该用什么工具调试一个程序?用什么办法才能找出程序中的错误?怎样才能从一开始就避免错误?,2.7.3.1应该用什么工具调试一个程序,调试工具功能观察程序的运行情况设置断点设置监视,2.7.3.2用什么办法才能找出程序中的错误,先调试程序中较小的组成部分,然后调试较大的组成部分彻底调试好程序的一个组成部分后,再调试下一个组成部分连续地观察程序流(flow)和数据的变化始终打开编译程序警告选项,并试图消除所有警告准确地缩小存在错误的范围,2.7.3.3如何从一开始就避免错误,程序中应有足够的注释函数应当简洁程序流应该清晰,避免使用goto语句和其它跳转语句函数名和变量名应具有描述性,2.7.4能报告条件失败的程序,assert()命令打印失败条件的内容;打印发生错误的行号;打印错误所在的源文件名;使程序以出错状态结束。NDEBUG宏定义,2.7.4能报告条件失败的程序,assert()例子,foo()char*buffer;buffer=malloc(10000);assert(buffer!=NULL);floatIntFrac(intNum,intDenom)assert(Denom!=0);return(float)Num

温馨提示

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

评论

0/150

提交评论