c语言指针完整ppt课件_第1页
c语言指针完整ppt课件_第2页
c语言指针完整ppt课件_第3页
c语言指针完整ppt课件_第4页
c语言指针完整ppt课件_第5页
已阅读5页,还剩76页未读 继续免费阅读

下载本文档

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

文档简介

.,1,第9章指针,.,2,特点,能直接对内存地址操作,使用灵活,实现动态存储管理,可以使程序简洁、紧凑、高效,用间接访问的方式改变数据的逻辑顺序,调用函数时可实现变量的引用传递,.,3,地址和指针的概念,变量的地址和变量的值,inti=3;floatj=6;doublek=9;,3,6.0,9.0,变量i,变量j,变量k,2200,2206,2202,2214,程序中定义的变量,系统根据它的类型给它分配一定长度的内存单元,该内存单元的起始地址即为变量的地址。,该内存单元的内容就是变量的值。,.,4,直接访问和间接访问,直接访问:,用变量名直接从它对应的地址存取内容。,如:intx=5,y=8,z=0;z=x+y;,13,直接从x和y对应的地址2200和2202取出内容5和8然后相加将结果13存入变量z对应的地址2204的单元中。,.,5,间接访问,定义一个存放地址的变量p(p的地址1500),将x的地址2200存放在变量p中。通过变量p取出地址2200,再按此地址存取其中的内容,就间接的完成了对x的存取。,当p的内容改为2202时,通过变量p取出地址2202,再按此地址,存取的就是变量y的内容。,p就是指针变量,5,8,0,变量x,变量y,变量z,2200,2202,2204,2202,.,6,指针变量的定义,一般形式:,基类型名*指针变量名,说明:,基类型名:指针变量所指向的变量的类型名称,指针变量名:所定义的指针变量的名称,*:表示它后面的变量名是指针类型,功能:,(1)定义该指针变量名为指向基类型的指针变量,为该变量分配存储单元,其长度等于存储地址的字节数。,(2)基类型确定用指针变量“间接”存取数据的存储单元个数和存储形式。该变量只能指向基类型数据。,.,7,指针变量的初始化,用=float*p=,可以用赋值语句给指针变量赋值:,floaty,*py;py=,.,8,指针变量的引用,引用指针变量的指针值与引用其它类型的变量一样直接用它的变量名,引用指针变量所指向的变量时,用“*指针变量名”,注意:指针变量的值与它所指向变量的值之间的差别,指针变量只有正确赋值后才能通过它访问指向的变量。,intx;,p=,int*p;,*p,*p=5;,5,.,9,指针变量的运算,1.,.,12,给变量赋值的两种方法,1.直接访问用变量名,如:inti;i=5;,2.间接访问通过指向变量i的地址的指针变量p赋值,如:inti,*p;p=,.,13,取地址运算符int*p=,运行结果:Inputm,n:123456m=123,main(),运行结果:min=6,max=8,例:通过交换指针变量值按大小顺序输出,.,15,指针变量作为函数的参数,以指针类型为函数的参数,作用是将变量的地址传入函数。,.,16,intx,y;int*pt1;*pt2;,x=8;y=6;,pt1=,if(xy)swap(pt1,pt2);,printf(x=%d,y=%dn,x,y);,swap(int*p1,int*p2),p=*p1;,*p1=*p2;,*p2=p;,intp;,8,main(),6,8,运行结果:x=6,y=8,intx,y;int*pt1;*pt2;,x=8;y=6;,pt1=,if(xy)swap(pt1,pt2);,swap(int*p1,int*p2),p=*p1;,*p1=*p2;,*p2=p;,intp;,printf(x=%d,y=%dn,x,y);,.,17,指针与数组,C语言中规定数组名是指针类型的符号常量,该符号常量值等于数组首元素的地址(简称数组首地址),它的类型是指向数组元素的指针类型。即数组名是指向该数组首元素的指针常量。,.,18,指向数组元素的指针,1.定义指向数组元素的指针变量,定义指向数组元素的指针变量与定义指向变量的指针变量的方法相同.如:,inta10;int*p;p=,由于数组名是指向0号元素的指针类型符号常量,所以a与p=a;p+;p+=3;,.,20,注意:指针变量的运算顺序。,+*p,*p+,*(+p),(*p)+四者之间的差别:,+*p,先给p指向的变量加1,然后取其值,(*p)+,先取p指向的变量值,然后该变量值加1,*p+,取p所指向变量的值,然后p增1,*+p,P先增1,然后取p所指向变量的值,.,21,main()inta4=1,2,3,4,b,c,d,e;int*p=a;b=*p+;printf(“n%d,%d,”,b,*p);c=*+p;d=+*p;printf(“%d,%d”,c,d);,运行结果1,2,3,4,.,22,通过指针引用数组元素,在inta10,*p=a;定义的情况下:,(1)p+i或a+i就是ai的地址。都要进行a+id的运算。,(2)*(p+i)或*(a+i)就是p+i或a+i所指向的数组元素ai。数组元素中的“”是变址运算符,相当于*(+),ai相当于*(a+i)。,(3)指向数组元素的指针变量也可带下标,如pi与*(p+i)等价。所以,ai,*(a+i),pi,*(p+i)四种表示法全部等价。,(4)注意p与a的差别,p是变量a是符号常量,不能给a赋值,语句a=p;a+;都是错的。,.,23,a,引用数组元素可用:1)下标法,如ai,pi。2)指针法,如*(p+i)或*(a+i),其中p是指向数组a的元素的指针变量。,.,24,main()inta10;int*p,i;for(p=a;p(a+10);p+)scanf(%d,p);printf(n);for(i=0;i10;i+)printf(%d,ai);,for(i=0;i10;i+)printf(%d,*(a+i);p=a;/*不能省略*/for(i=0;i10;i+,p+)printf(%d,*p);for(p=a;p(a+10);p+)printf(%d,*p);,例.输入/输出数组全部元素,.,25,用字符型指针访问字符数组和字符串,【例9.5】用字符型数组名和字符指针变量两种方法整体输入/输出字符串。,main()chars81=Hello!,*p=s;char*ps=Welcometoyou!;printf(%sn,s);printf(%sn,ps);gets(s);printf(%sn,s);gets(p);printf(%sn,s);,.,26,字符指针变量和字符数组的区别,(1)存储的内容不同:,字符数组存储着字符串的内容,而字符指针变量存放的是字符串首元素的地址,不是它的内容。,(2)分配的内存单元不同:,字符数组分配一段有确定地址的内存。而指针变量只分配存放地址的内存单元,该指针变量可以指向一个字符型数据,但若未赋初值,则它并未指向一个明确的地址。此时它指向的变量并不存在。,.,27,(3)赋值方法不同:,对字符数组只能在定义时整体赋初值,不能用赋值语句整体赋值。赋值语句只能对各个元素分开赋值。,如:chars16;s=Iamastudent.;,chars16=Iamastudent.;,对字符指针变量,可以采用下面方法赋值:char*p;p=Iamastudent.;,(4)指针变量的值是可以改变的,字符数组名是地址常量其值是不能改变的。,.,28,数组或指针变量作函数参数,如:main()f(inta,intn)intarray10;.f(array,10).,.,29,由于数组名代表首地址,能接收并存放地址值的只能是指针变量。故编译系统将形参数组名作为指针变量来处理。例中函数首部f(inta,intn)可写成f(int*a,intn)两种完全等价。,.,30,归纳起来,如果有一个数组,想在被调用的函数中改变其元素的值,实参与形参的对应关系有以下四种:,(1).实参和形参都用数组名。(2).实参用数组名,形参用指针变量。(3).实参用指针变量,形参用数组名。(4).实参和形参都用指针变量。,实质都是地址值的传递,.,31,【例9.7】通过调用函数,将整型数组的所有元素加10。参数传递用四种方法实现。,voidadd(intb,intn)inti;for(i=0;in;i+)bi+=10;main()inti,a10=1,2,3,4,5,6,7,8,9,10;add(a,10);for(i=0;i10;i+)printf(%4d,ai);,voidadd(int*p,intn)int*pend=p+n;for(;ppend;p+)*p+=10;main()inti,a10=1,2,3,4,5,6,7,8,9,10;add(a,10);for(i=0;i10;i+)printf(%4d,ai);,voidadd(intb,intn)inti;for(i=0;in;i+)bi+=10;main()inti,a10=1,2,3,4,5,6,7,8,9,10;int*q=a;add(q,10);for(i=0;i10;i+)printf(%4d,ai);,voidadd(int*p,intn)int*pend=p+n;for(;ppend;p+)*p+=10;main()inti,a10=1,2,3,4,5,6,7,8,9,10;int*q=a;add(q,10);for(i=0;i10;i+)printf(%4d,ai);,.,32,用字符数组或指针做函数参数传递字符串,将字符串从一个函数传递到另一个函数,可以用地址传递的方法,即用字符数组名或用字符指针变量作参数。在被调用的函数中可以改变字符串中的内容,在主调函数中可以得到改变了的字符串。,.,33,【例9.8】字符串复制函数主要功能的实现。,(1)用字符数组作参数,voidstrcpy(chars1,chars2)inti=0;while(s2i!=0)s1i=s2i;i+;s2i=0;main()chara20=Iamateacher.;charb=youareasrudent.;printf(stringa=%snstringb=%sn,a,b);strcpy(a,b);printf(nstringa=%snstringb=%sn,a,b);,.,34,(2)形参用字符指针变量。,程序如下:voidstrcpy(char*s1,char*s2)for(;*s2!=0;s2+,s1+)*s1=*s2;*s1=0;main()chara20=Iamateacher.;char*b=youareasrudent.;printf(stringa=%snstringb=%sn,a,b);strcpy(a,b);printf(nstringa=%snstringb=%sn,a,b);,while(*s1=*s2)!=0)s1+;s2+;*s1=0;,while(*s2!=0)*s1+=*s2+;*s1=0;,while(*s2)*s1+=*s2+;*s1=0;,while(*s1+=*s2+)!=0),while(*s1+=*s2+),.,35,多维数组和指向分数组的指针,多维数组的地址,以二维数组为例,设二维数组a有3行4列。inta34=1,2,3,4,5,6,7,8,9,10,11,12,a是数组名,a数组有3行,即3个分数组:a0,a1,a2。每个分数组又是含4个列元素的一维数组。,.,36,2000,基类型,行指针与列指针,a23*(a2+3)*(*(a+2)+3),+3,+2,+1,+0,a0,a0,a0,a0,*(a+0),*(a+0),*(a+0),*(a+0),+3,+2,+1,+0,a1,a1,a1,a1,*(a+1),*(a+1),*(a+1),*(a+1),.,37,注意,a+1与a0+1不同a+1是a第1行分数组地址*(a+1)是第1行数组名*(a+1)是元素a10a0是第0行分数组名a0+1是元素a01地址*(a0+1)是元素a01,.,38,形式含义内容a,int*p;for(p=a0;pa0+15;p+)if(p-a0)%5=0)printf(n);printf(%4d,*p);,.,40,定义形式:数据类型(*指针名)一维数组维数;,一维数组指针变量维数和二维数组列数必须相同。,例:inta34,(*p)4=a;,2.指向分数组的指针,.,41,p0+1,p,或*p+1,p1+2,p+1,或*(p+1)+2,p+2,inta34;int(*p)4=a;,.,42,例:用指向二维数组的分数组的指针变量,按行输出。main()inta34=1,2,3,4,5,6,7,8,9,10,11,12;int*q,(*p)4;for(p=a;pa+3;p+)for(q=*p;q*p+4;q+)printf(%5d,*q);printf(n);,注意:int(*p)5;表示p是一个指针变量,可以指向含有5个元素的一维数组,其中每个元素都是整型的。如果定义为int*p5;由于“”优先级高,则表示p首先是数组,它有5个元素,每个元素为指向整型变量的指针。,.,43,用多维数组名和指针变量作函数参数,(1)用多维数组名作实参或形参。,如:f(inta4,intn);,(2)用指向元素的指针变量作实参或形参。,如:f1(int*p);,(3)用指向分数组的指针变量作函数参数。,如:f2(int(*q)4,intm);,.,44,【例9.16】用两个二维数组存储矩阵,调用函数求两个矩阵之差,差矩阵存放在第一个实参数组中,用指向分数组的指针变量作形参。矩阵输出也用函数实现。,#defineN4sub(int(*p1)N,int(*p2)N,intm)int*q1,*q2,(*u)N;u=p1+m;for(;p1u;p1+,p2+)for(q1=*p1,q2=*p2;q1*p1+N;q1+,q2+)*q1-=*q2;print(int(*p)N,intm)int*q,(*u)N;u=p+m;for(;pu;p+)for(q=*p;q*p+N;q+)printf(%6d,*q);printf(n);printf(n);main()inti,j,aN=1,2,3,4,5,6,7,8;intbN=10,20,30,40,50,60,70,80;print(a,2);print(b,2);sub(b,a,2);print(b,2);,.,45,指针数组,如果每个数组元素均为指针类型的变量,即数组元素的类型是指针类型,则称这样的数组为指针数组。,一维指针数组的定义形式为:基类型名*数组名数组长度=地址初值列表,例如:inti,j,k,m,n;int*q5=,.,46,main()chara=Program;charb=Fortran;charc=Basic;char*p4;p0=a;p1=b;p2=c;p3=NULL;,char*p4,0,或:main()char*p4;p0=Program;p1=Fortran;p2=Basic;p3=NULL;,初始化:main()char*p=Program,Fortran,Basic,NULL;,.,47,用指针数组处理多个字符串,例:将5个字符串递增排序后输出。#include#includemain()char*pccolor=red,blue,yellow,green,purple;intn=5;printf(Beforesortingis:n);OutPut(pcolor,n);Sort(pcolor,n);printf(Aftersortingis:n);OutPut(pcolor,n);,.,48,voidSort(char*a,intn)inti,j,k;char*t;for(i=0;in-1;i+)for(j=i+1;j0),.,49,voidOutPut(char*a,intn)inti;for(i=0;i0)printf(%s%c,*+argv,(argc1)?:n);,在操作系统命令行状态下输入:echoWelcometoyou!,执行后输出以下信息:Welcometoyou!,.,57,【例9.18】实现系统提供的字符串复制函数strcpy()的全部功能。,char*strcpy(char*s1,char*s2)char*p=s1;while(*s1+=*s2+);return(p);main()chars20;printf(%sn,strcpy(s,Welcometoyou!);,.,58,结构体与指针,指向结构体变量的指针,结构体指针变量的定义:struct结构体名*指针变量名;例如:structstudent*pt=,structstudentintnum;charname20;charsex;intage;stu;,.,59,使用结构体指针变量引用成员形式,(*结构体指针名).成员名,结构体指针名-成员名,结构体变量名.成员名,structstudentintnum;charname20;charsex;intage;stu;structstudent*p=,(*p).num,p-num,stu.num,p=charname20;charsex;intage;main()structstudentstu,*p;p=,.,61,例:结构体数组指针的使用,structstudentintnum;charname20;charsex;intage;stu3=10101,LiLin,M,18,10102,ZhangFun,M,19,10103,WangMin,F,20;main()structstudent*p;for(p=stu;pnum,p-name,p-sex,p-age);,10101,LiLin,M,18,10102,ZhangFun,M,19,10103,WangMin,F,20,.,62,结构体指针作函数参数,用结构体变量的成员作参数-单值传递用结构体变量作参数-多值传递用指向结构体变量或数组的指针作参数-地址传递。,.,63,【例9.17】采用“引用传递”的方式,用指向结构体的指针变量作参数,在input函数中输入并计算平均成绩,在main函数输出。,#defineN4#include#defineFMT%5d%-11s%5d%8d%8d%10.1fnstructstintnum;charname11;ints3;floataver;voidinput(structst*p)scanf(%d%s%d%d%d,.,64,指针与链表,链表可以动态的进行存储分配,head:头指针,存放一个地址,指向链表中的第一个元素.,每一个元素称为一个“结点”,每个结点都包括两部分:,1.用户需要的实际数据;,2.下一个结点的地址.,表尾:它的地址部分放一个“NULL”,链表到此结束.,.,65,可用结构体类型的变量来存储链表中的结点元素.,每一个结点中存放地址的部分可用指针来实现.,例:structstudentintnum;floatscore;structstudent*next;,.,66,简单静态链表,#defineNULL0structstudentlongnum;floatscore;structstudent*next;main()structstudenta,b,c,*head,*p;a.num=9901;a.score=89.5;b.num=9903;b.score=90;c.num=9905;c.score=85;head=,9901,89.5,9903,90,9905,85,作用是:在内存的动态存储区分配一个长度为size的连续空间,原型说明在“stdlib.h”头文件和“alloc.h”头文件中,.,68,2.calloc函数,void*calloc(unsignedn,unsignedsize);,作用是:在内存的动态区分配n个长度为size的连续空间.,3.free函数,voidfree(void*p);,作用是:释放由p指向的内存区.,.,69,typedefstructNodeintdata;structNode*next;Node;,链表的插入操作,s-next=pre-next;,pre-next=s;,顺序可以颠倒吗?,voidInsList(Node*L,inti,inte)Node*pre,*s;intk=0;pre=L;while(pre!=NULL,.,70,链表的删除操作,pre-next=pre-next-next;,free(r);,voidDelList(Node*L,inti)Node*pre,*r;pre=L;intk=0;while(pre-next!=NULL,.,71,建立动态链表,头插法建表,尾插法建表,头插法建表,s指向新申请的结点s-data=A;,插入第一个结点:,插入某一个结点:,s-next=H-next;,H-next=s;,顺序可以颠倒吗?,.,72,LinklistCreateFromHead()Node*s,*L;charc;intflag=1;L=(Node*)malloc(sizeof(Node);L-next=NULL;while(flag)c=getchar();if(c!=$)s=(Node*)ma

温馨提示

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

评论

0/150

提交评论