C语言第10章(谭浩强).ppt

上传人:tia****nde 文档编号:12706215 上传时间:2020-05-14 格式:PPT 页数:80 大小:413.50KB
返回 下载 相关 举报
C语言第10章(谭浩强).ppt_第1页
第1页 / 共80页
C语言第10章(谭浩强).ppt_第2页
第2页 / 共80页
C语言第10章(谭浩强).ppt_第3页
第3页 / 共80页
点击查看更多>>
资源描述
1,第10章指针,指针可以有效地表示复杂的数据结构;能动态的分配内存、使用字符串和数组;能在调用函数时获得1个以上的结果;能直接处理内存单元地址等。掌握指针的应用,可以使程序简洁、紧凑、高效。,2,10.1地址和指针的概念一、变量的地址计算机内存区的每一个字节都有一个编号。在对程序进行编译时,系统会给变量分配内存单元,这个内存单元的地址就是变量的地址。系统根据不同的数据类型分配不同字节的空间。,内存单元地址内存单元内容不同,编译时是把变量名转换为变量的地址如:scanf(“%d”,3,二、变量的访问方式1.直接访问按变量地址存取变量值的方式称为“直接访问”方式。2.间接访问假如定义变量j存放变量i的地址。,如:j=,4,三、指针变量由于通过地址可以找到所需变量的存储单元,所以c语言把地址称为指针。指针:一个变量的地址称为该变量的指针。例如:地址2000是变量i的指针。指针变量:专门存放变量地址的变量叫指针变量。注意:指针和指针变量的区别如:j为指针变量,它存放整型变量i的地址我们称,指针变量j指向整型变量i,5,10.2变量的指针和指向变量的指针变量变量的指针就是变量的地址。存放变量地址的变量是指针变量,用来指向另一个变量。,6,注意:在c程序中用*表示指向,若定义了i_pointer为指针变量,那么*i_pointer就是i_pointer指向的那个变量。*i_pointer相当于i都代表3(值),/*指针i_pointer指向了变量i*/,一、如何定义一个指针变量形式:基类型*指针变量名指针只能指向基类型规定的类型变量例如:inti,j;floatx;int*i_pointer,*j_pointer;那么,如何使一个指针变量指向另一个变量呢?可以:i=3;i_pointer=,7,在定义指针变量时注意:,(1)定义指针变量时,变量前面的*是表示该变量是指针型的,其变量名是i_pointer,而不是*i_pointer(2)定义指针变量必须指定其类型。为什么?当i_pointer+时,加1代表多少字节才能确定。总结:一个指针变量只能指向同一类型的变量。如:floata;int*pointer;pointer=(错),8,二、指针变量的引用指针变量中只能存放地址(指针),两个运算符:1.,强调*定义和引用时的区别,9,输出:100,10100,10,*pointer_1=,例10.1通过指针变量访问整型变量main()inta,b;int*pointer_1,*pointer_2;/*区分定义和引用时的区别*/a=100;b=10;pointer_1=,10,说明:若:p1=p2=scanf(“%d,%d”,13,三、指针变量作为函数参数函数的参数可以是整型、实型、字符型等数据或者是数组,还可以是指针类型的。它的作用是将一个变量的地址传送到另一个函数中。,14,例10.3同例10.2输入a和b两个整数,按大小的顺序输出.,main()int*p1,*p2,a,b;scanf(“%d,%d”,voidswap(int*p1,int*p2)inttemp;temp=*p1;*p1=*p2;*p2=temp;,/*指针变量作函数参数,把变量a和b的地址传给形参,这时实参和形参都指向变量a和b*/,/*定义形参,所以要带*/,/*把变量a和b的值交换*/,注意:a和b的值改变了。,15,指针变量作函数参数时,注意:1.指针变量,既可以作为函数的形参,也可以作函数的实参。2.指针变量作实参时,与普通变量一样,也是“值传递”,即将指针变量的值(一个地址)传递给被调用函数的形参(必须是一个指针变量)。注意:被调用函数不能改变实参指针变量的值,但可以改变实参指针变量所指向的变量的值。,16,例10.4输入a、b、c3个整数,按大小顺序输出。,voidswap(int*pt1,int*pt2)/*指针变量作函数形数*/inttemp;temp=*pt1;*pt1=*pt2;*pt2=temp;/*交换变量*/,voidexchange(int*q1,int*q2,int*q3)/*判断大小*/if(*q1*q2)swap(q1,q2);/*指针变量作函数实参*/if(*q1*q3)swap(q1,q3);if(*q2*q3)swap(q2,q3);,main()inta,b,c,*p1,*p2,*p3;scanf(“%d,%d,%d”,17,10.3数组的指针和指向数组的指针变量,既然指针可以指向变量,当然也能指向数组。数组的元素是连续存放的:一般,用下标法表示数组元素,如:a3,10.3.1指向数组元素的指针如何定义指向数组的指针变量?定义与指向普通变量的指针变量的定义方法一样。例如:inta10,*pointer=a;或者:inta10,*pointer;pointer=a;以上是在语句中赋值,分为两步。,inta5=2,4,8,16,32;p1=,2,4,8,16,32,a0,a1,a2,a3,a4,p1,p2,p3,19,10.3.2通过指针引用数组元素如:inta3,*p=a;*p=1;/*相当于a0=1*/(p=1;)(错)注意:当p+1时,则指针p指向同一数组的下一个元素,而不是把地址加1。当p为int型时:p+1相当于使p的值(地址)加2个字节;当p为float型时:p+1相当于使p的值(地址)加4个字节;所以:p+1代表的地址=p+1*d,/*d为数组元素的类型所占的字节数*/,20,说明:如果有inta10,*p=a;,则:(1)p+i和a+i都可以表示数组元素ai的地址,或者说它们都指向a数组的第i个元素。例如:p+9a+9(2)*(p+i)和*(a+i)就是数组元素ai的值。例如:*(p+5)*(a+5),值都是for(i=0;i10;i+)scanf(“%d”,(3)用指针变量指向数组元素voidmain()inta10,i,*p;for(i=0;i10;i+)scanf(“%d”,(2)用数组名计算数组地址,找到元素的值voidmain()inta10,i;for(i=0;i10;i+)scanf(“%d”,第1、2种方法效率相同,第3种方法的效率更高,for(i=0,p=a;p(a+10);p+)printf(%d,pi);,23,使用指针变量指向数组元素时,需注意:(1)可以通过改变指针变量的值使其指向不同的元素,如p+但是不能用数组名a+(2)使用指针变量,要注意指针的当前值。如下例,main()int*p,i,a5;p=a;for(i=0;i5;i+)scanf(“%d”,p+);printf(“n”);,for(i=0;i5;i+,p+)printf(“%d”,*p);printf(“n”);,p=a;,/*输出数组元素*/,解决办法:?,(3)由上例得出,指针变量可以指向数组以外的内存单元,系统不会报错。,24,*(p+)a0*(+p)a1,若pa0,则,注意:(4)指针变量的运算。p=a;/*指针p指向了数组a的首地址*/1)p+/*使p指向下一个元素*/2)*p+*(p+)/*先得到*p的值,指针p指向下一地址*/如:for(i=0;i5;i+,p+)printf(“%d”,*p);3)*(p+)与*(+p)不同,可改为:for(i=0;i=:判断两个指针指向的数据位置的前后关系=,!=:判断两个指针是否指向同一个数据7)指针变量可以有空值,即该指针变量不指向任何变量。p=NULL;,27,10.3.3用数组名作函数参数数组名作实参时:起始地址形参数组;数组名作形参时:接收实参数组的起始地址实际上,c编译是把形参数组名作为指针变量来处理。如:f(inta,intn)f(int*a,intn),等价,28,例10.7请把数组a中的n个元素按相反的顺序存放。,算法:a0an-1a1an-2aint(n-1)/2an-int(n-1)/2)-1,设循环变量i,ji=0;j=n-1aiaj交换;直到i=(n-1)/2。,i:0(n-1)/2(n-1):j-,29,main()inti,a10=3,5,2,6,8,9,0,1,7,4;for(i=0;i10;i+)printf(%d,ai);printf(n);inv(a,10);/*数组名a作实参*/for(i=0;i10;i+)printf(%d“,ai);,程序:,voidinv(intx,intn)/*数组名x作形参*/inttemp,i,j,m=(n-1)/2;for(i=0;i=m;i+)j=n-1-i;temp=xi;xi=xj;xj=temp;,voidinv(int*x,intn)/*指针变量x作形参*/inttemp,*i,*j,*p,m=(n-1)/2;i=x;j=x+n-1;p=x+m;for(;i=p;i+,j-)temp=*i;*i=*j;*j=temp;,指针变量能否作形参?,30,总结:数组及指向数组的指针变量作函数参数时,可有种等价形式P238-239(本质上是一种,即指针数据作函数参数):(1)形参、实参都用数组名(2)形参、实参都用指针变量(3)形参用指针变量,实参用数组名(4)形参用数组名,实参用指针变量,31,10.3.4指向多维数组的指针多维数组元素的地址inta34=1,3,5,7,9,11,13,15,17,19,21,23,a数组包括3个元素:a0a1a2,而每个元素又是一个一维数组。因此:aa0第0行printf(FORMAT,a,*a);printf(FORMAT,a0,*(a+0);printf(FORMAT,例10.10输出二维数组有关的值,/*第0行首地址,0行0列元素地址*/,/*第0行0列元素地址*/,/*第0行首地址,第0行0列元素地址*/,/*第1行0列元素地址,第1行首地址*/,/*第1行0列元素地址*/,/*第2行0列元素地址*/,/*第2行首地址*/,/*第1行0列元素的值*/,36,2.指向多维数组的指针变量(1)指向数组元素的指针变量例10.11用指针变量输出数组元素的值。main()inta34=1,3,5,7,9,11,13,15,17,19,21,23;int*p;for(p=a0;pa0+12;p+)if(p-a0)%4=0)printf(“n”);printf(“%4d”,*p);,/*a0代表第0行0列元素地址*/,37,aij在数组(n*m)中的相对位置计算公式:i*m+j(m为数组的总列数)如:a23位置=2*4+3(2)指向由m个元素组成的一唯数组的指针变量例10.11的指针变量p是指向整型数据的,p+1表示指向下一个元素。可以使p不指向整型数据,而指向包含m个元素的一唯数组,这样p+1就表示下一行元素的首地址。,地址?,int(*p)4,i,j;p=a;scanf(“%d,%d”,/*表示p所指的对象是有4个整型元素的数组,p只能指向一个包含4个元素的一唯数组*/,*p,*(p+1),输入:1,1输出:11,更改后:输入:1,1输出:3,39,3.用指向数组的指针作函数参数例10.13有一个班,3个学生,4门成绩。求所有成绩的平均分,第2个学生的各门成绩。,average(float*p,intn)float*p_end;floatsum=0,aver;p_end=p+n-1;for(;py)z=x;elsez=y;return(z);,intmin(intx,inty)intz;if(xy)z=x;elsez=y;return(z);,intadd(intx,inty)intz;z=x+y;return(z);,voidprocess(intx,inty,int(*fun)(int,int)intresult;result=(*fun)(x,y);printf(“%dn”,result);,voidmain()inta,b;scanf(“%d,%d”,/*函数的入口地址*/,55,10.6返回指针值的函数,一个函数可以返回一个int型、float型、char型的数据,也可以返回一个指针类型的数据。返回指针值的函数(简称指针函数)的定义格式如下:函数类型*函数名(形参表)floatsearch(float(*p)4,intn)float*tp;tp=*(p+n);return(tp);,56,cccccint*seek(int(*pnt_row)3)inti=0,*pnt_col;/*定义一个(列)指针变量pnt_col*/pnt_col=*(pnt_row+1);/*使pnt_col指向下一行之首(作标志用)*/for(;i3;i+)if(*(*pnt_row+i)60)/*某项成绩不合格*/pnt_col=*pnt_row;/*使pnt_col指向本行之首*/break;/*退出循环*/return(pnt_col);,57,/*主函数main()*/main()intgrade33=55,65,75,65,75,85,75,80,90;inti,j,*pointer;/*定义一个(列)指针变量pointer*/for(i=0;i3;i+)/*控制每个学生*/pointer=seek(grade+i);/*用行指针作实参,调seek()函数*/if(pointer=*(grade+i)/*该学生至少有一项成绩不合格*/*输出该学生的序号和各项成绩*/printf(“No.%dgradelist:”,i+1);for(j=0;j3;j+)printf(“%d”,*(pointer+j);printf(“n”);程序运行结果:No.1gradelist:556575,58,程序说明:(1)主函数中的pointer=seek(grade+i);语句调用seek()函数时,将实参grade+i(行指针)的值,复制到形参pnt_row(行指针变量)中,使形参pnt_row指向grade数组的第i行。(2)在指针函数seek()中:1)pnt_col=*(pnt_row+1);语句*(pnt_row+1)将行指针转换为列指针,指向grade数组的第i+1行第列,并赋值给(列)指针变量pnt_col。2)if(*(*pnt_row+i)60)行pnt_row是一个行指针,指向数组grade的第i行;*pnt_row使指针由行转换为列,指向数组grade的第i行列;*pnt_row+j的值还是一个指针,指向数组的第i行第j列;*(*pnt_rowj)是一个数据(数组元素gradeij的值)。,59,10.7指针数组和指向指针的指针,10.7.1指针数组的概念一个数组,其元素均为指针类型数据,称为指针数组。数组的每个元素都是一个指针数据。指针数组比较适合用于指向多个字符串,使字符串处理更加方便、灵活。定义格式:数据类型*数组名元素个数例如:int*p4由于比*优先级高,因此P先与4结合,形成P4形式,然后再与P前面的“*”结合,“*”表示此数组是指针类型的,每个数组元素相当于一个指针变量,都可指向一个整型变量。例:有若干计算机图书,请按字母顺序,从小到大输出书名。解题要求:使用排序函数完成排序,在主函数中进行输入输出。/*程序功能:指针数组应用示例*/,60,voidsort(char*name,intcount)char*temp_p;inti,j,min;/*使用选择法排序*/for(i=0;i0)/*存在更小的串*/min=j;/*保存之*/if(min!=i)/*存在更小的串,交换位置*/temp_p=namei;namei=namemin;namemin=temp_p;,61,main()char*name5=“BASIC”,”FORTRAN”,”PASCAL”,”C”,”FoxBASE”;inti=0;sort(name,5);/*使用字符指针数组名作实参,调用排序函数sort()*/for(;i5;i+)printf(“%sn”,namei);/*输出排序结果*/程序运行结果:BASICCFORTRANFoxBASEPASCAL,62,程序说明:(1)实参对形参的值传递:sort(name,5);voidsort(char*name,intcount)(2)字符串的比较只能使用strcmp()函数。形参字符指针数组name的每个元素,都是一个指向字符串的指针,所以有strcmp(namemin,namej)。主函数main()的形参在以往的程序中,主函数main()都使用其无参形式。实际上,主函数main()也是可以指定形参的。案例:用同一程序实现文件的加密和解密。约定:程序的可执行文件名为lock.exe,其用法为:lock+|-,其中“+”为加密,“-”为解密。,63,main(intargc,char*argv)ccccccharc;if(argc!=3)printf(参数个数不对!n);elsec=*argv1;/*截取第二个实参字符串的第一个字符*/switch(c)case+:/*执行加密*/printf(执行加密程序段。n);/*加密程序段*/break;case-:/*执行解密*/printf(执行解密程序段。n);/*解密程序段*/break;default:printf(第二个参数错误!n);,64,1.主函数main()的有参形式main(intargc,char*argv)2.实参的来源运行带形参的主函数,必须在操作系统状态下,输入主函数所在的可执行文件名,以及所需的实参,然后回车即可。命令行的一般格式为:可执行文件名实参实参2本程序的用法:lock+|-在TC的集成环境下,也可直接利用Options|Arguments项,输入主函数所需要的实参:只须输入各参数(相邻参数间用空格分开),可执行文件名可省略。就本案例而言,输入“+|-”即可。,65,3.形参说明(1)形参argc是命令行中参数的个数(可执行文件名本身也算一个)。在本案例中,形参argc的值为3(lock、+|-、文件名)。(2)形参argv是一个字符指针数组,即形参argv首先是一个数组(元素个数为形参argc的值),其元素值都是指向实参字符串的指针。在本案例中,元素argv0指向第1个实参字符串“lock”,元素argv1指向第2个实参字符串“+|-”,元素argv2指向第3个实参字符串“被处理的文件名”。,66,10.7.2指向指针的指针指向指针数据的指针变量,简称为指向指针的指针。怎样定义一个指向指针数据的指针变量呢?形式:char*p;相当于*(*p),显然*P是指针变量的定义形式。现在又加一个*号,表示指针变量P是指向一个字符指针变量的。*P就是P所指向的另一个指针变量。,67,例10.28指向指针的指针的应用main()char*name=“f0llowme”,”basic”,greatwall”,”fortran”,computerdesign”);char*p;inti;for(i=0;i5;i+)p=name+I;printf(“%sn”,*p);,68,指向指针的指针变量简介在案例的主函数main()中,数组name是一个字符指针数组,即数组的每一个元素都是一个指向字符串的指针。既然name是一个数组,则它的每一个元素也同样有相应的地址,因此可以设置一个指针变量pointer,使其指向指针数组的元素(元素的值还是一个指针),称pointer为指向指针的指针变量。显然,指向指针的指针变量是一个两级的指针变量。1.指向指针的指针变量的定义数据类型*指针变量,*指针变量2;2.指向指针的指针变量的赋值指针变量=指针数组名+i,69,例如10.29指针数组的元素指向数据main()staticinta5=(1,3,5,7,9;int*num5=输出结果:,70,10.8有关指针的数据类型和指针的小结10.8.1有关指针的数据类型的小结inti定义整型变量iint*p;P为指向整型数据的指针变量intan;整型数组a有n个元素int*pn;P由n个指向数据的指针元素组成int(*p)n;P为指向n个元素的数组的指针变量intf();f为带回整型函数值的函数int*p();P为带回一个指针的函数,该指针指向整数int(*p)();P为指向函数的指针,返回一个整型值int*p;p指针变量指向整型数据的指针变量,71,二10.8.2指针运算小结1)指针变量加、减:P+P-P+iP-iP+=iP-=等2)指针变量赋值:P=void*p2;p1=(char*)p2;void*指针类型是ANSI系统新加的,若详细了解可参阅有关手册。,73,有以下程序#includemain()intm=1,n=2,*p=程序运行后的输出结果是BA)1,2,1,2B)1,2,2,1C)2,1,2,1D)2,1,1,2,74,有以下程序#include#includemain()charstr20=“One*World”,“One*Dream!”,*p=str1;printf(“%d,”,strlen(p);printf(“%sn”,p);程序运行后的输出结果是CA)9,One*WorldB)9,One*DreamC)10,One*Dream!D)10,One*World,/*p指向了第1行0列元素的地址*/,75,下列函数的功能是Afun(char*a,char*b)while(*b=*a)!=0)a+,b+;A)将a所指字符串赋给b所指空间B)使指针b指向a所指字符串C)将a所指字符串和b所指字符串进行比较D)检查a和b所指字符串中是否有0,76,若有定义语句:inta410,*p,(*q)4;且0i4,则错误的赋值是B/*q是指向一维数组的指针*/A)p=aB)qi=aiC)p=aiD)p=printf(“%d,%dn”,strlen(a),sizeof(a);程序运行后的输出结果是BA)7,4B)4,10C)8,8D)10,10,strlen(a)测定a中不包括0字符个数;sizeof(a)测定a所占的字节数。,78,设有以下函数voidfun(intn,char*s)则下面对函数指针的定义和赋值均是正确的是AA)void(*pf)();pf=fun;B)viod*pf();pf=fun;C)void*pf();*pf=fun;D)void(*pf)(int,char);pf=,79,设有定义:char*c;,以下选项中能够使字符型指针c正确指向一个字符串的是AA)charstr=”string”;c=str;B)scanf(“%s”,c);C)c=getchar();D)*c=”string”;,80,intf(intn);main()inta=3,s;s=f(a);s=s+f(a);printf(“%dn”,s);intf(intn)staticinta=1;n+=a+;returnn;程序运行以后的输出结果是CA)7B)8C)9D)10,
展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 图纸专区 > 课件教案


copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!