资源描述
单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,/,*,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,第十七讲 指针(一),/,学习目标,理解变量、内存单元和地址之间的关系,能够定义、使用指针,掌握指针变量的基本运算,会使用指针作为函数的参数,/,8.1,寻找保险箱密码,一个关于特工00,7,寻找保险箱密码的故事,关键点分析,得到线索:0217单元的“虎跑号”寄存箱,提示地址:1976单元,找到目标:“龙井号”寄存箱,取出内容:911,/,8.1 寻找密码的途径分析,密码911存放在某个寄存箱内,如果我们知道这个寄存箱的名字,就能够找到密码,.,如果不知道密码所在的寄存箱名字,知道该寄存箱的地址也照样能够取出密码,.,如果寄存箱的地址也不知道,但是有另外一个地方存放这个寄存箱的地址,就能顺藤摸瓜,间接找到密码,.,/,8.1 密码存放示意图,龙井号,911,1976,虎跑号,1976,0217,名字,虎跑号,龙井号,地址,0217,1976,内容,1976,911,/,例8,-1,利用指针模拟寻找保险箱密码的过程,获取密码的两种方法,int,main(void),int,key=911;/*,变量,key,存放密码,*/,int,*,addr,=,NULL,;/*,变量,addr,存放地址,*/,addr,=,/*,将,key,的地址赋给,addr,*/,/*,通过变量,key,输出密码值,*/,printf(The,key is:%dn,key);,/*,通过变量,key,的地址来输出密码值,*/,printf(If,I know the address of the key,I also can get it:%dn,*,addr,);,return 0;,The key is:911,If I know the address of the key,I also can get it:911,/,8.1.2 地址和指针,指针,的,概念,内存单元,地址 内容,变量,int,x=20,y=1,z=155;,printf(%d,x;),直接访问,:通过变量名访问,间接访问,:,通过,另一个变量访问,把变量的地址放到另一变量中,使用时先找到后者,再,从中取出前者的地址,1000 20,x,1002 1,y,1004 155,z,2000 1000,p,2002,地址,指针变量,/,指针,内存单元,地址 内容,变量,int,x=20,y=1,z=155;,printf(%d,x;),1000 20,x,1002 1,y,1004 155,z,2000 1000,p,2002,地址,指针变量,指针变量,:存放地址的变量,某个,变量,的地址,指向,/,指针变量所指向的变量的类型,int,*p;,p,是整型指针,指向整型变量,float*,fp,;,fp,是浮点型指针,指向浮点型变量,char*cp;,cp,是字符型指针,指向字符型变量,类型名,*,指针变量名,指针声明符,8.1.3 指针变量的定义,/,指针变量的定义,类型名,*,指针变量名,int,*,p,;,指针变量名是,p,,,不是,*,p,。,*,是指针声明符,p,里保存一个地址,这个地址在哪里?(,p,指向哪里?),int,k,*p1,*p2;,等价于:,int,k;,int,*p1;,int,*p2;,/,指针变量的初始化,一般形式:,存储类型,数据类型,*,指针名,=,初始地址值,;,赋给指针变量,例,int,i;,int,*p=,&i,;,变量必须,已说明过,类型,应一致,例,int,*p=,&i,;,int,i;,例,int,i;,int,*p=,&i,;,int,*q=,p,;,用已初始化指针变量作初值,例,main(),int,i;,static,int,*p=,.,(,),不能用,auto,变量的地址,去初始化,static,型指针,/,例,#include,void,main(),int,i=10;,int,*p;,*p=i;,printf(“%d,”,*p);,例,#include,void main(),int,i=10,k;,int,*p;,p=,*p=i;,printf(“%d,”,*p);,指针变量的初始化,一般形式:,存储类型,数据类型 *指针名,=,初始地址值;,/,零指针与空类型指针,零指针:,(,空指针,),定义,:,指针变量值为零,表示:,int,*p=0;,p,指向地址为0的单元,,,系统保证该单元不作它用,表示指针变量值,没有意义,#define,NULL,0,int,*p=NULL:,p=NULL,与未对,p,赋值不同,用途:,避免指针变量的非法引用,在程序中常作为,状态,比较,例,int,*p;,.,while(,p!=NULL,),.,void *,类型指针,表示,:void *p;,使用时要进行,强制类型转换,例,char *p1;,void *p2;,p1=(char *)p2;,p2=(void*)p1;,表示不指定,p,是指向哪一种,类型数据的指针变,量,/,变量的指针和指针变量,变量的指针,内存中存储某个变量的存储单元的首地址。,指针,(,地址,),实质上是一个整数,(,不是,C,的整型,),。,可以通过变量的地址来间接的访问变量。,指针变量,指针,(,地址,),是一个数据,也可以用另一个变量来存放,即指针变量。,通过指针变量可以间接访问变量或内存数据。,/,8.1.4,指针的基本运算,*,间接访问运算符,,,访问指针所指向的变量,*,p,:,指针变量,p,所,指向的,变量,a,3,&,a,p,*,p,如果指针的值是某个变量的地址,通过指针就能,间接访问,那个变量。,1,、取地址运算和间接访问运算,&,取地址运算符,,,给出变量的地址,int,*p,a=3;,p=,把,a,的地址赋给,p,,即,p,指向,a,指针变量的类型和它所指向变量的类型相同,/,#include,int,main(void),int,a=3,*p;,p=,printf,(,“,a=%d,*p=%dn,”,a,*p);,*,p=10;,printf(,a,=%d,*p=%dn,a,*p);,printf(,Enter,a:,);,scanf(,%d,printf(,a,=%d,*p=%dn,a,*p);,(*p)+;,printf(,a,=%d,*p=%dn,a,*p);,return 0;,例8-2,指针取地址运算和间接访问运算,a,3,&,a,p,*,p,a=3,*p=3,a=10,*p=10,Enter a:,5,a=5,*p=5,a=6,*p=6,/,a,3,&,a,p,*,p,(1)当,p=&a,后,*,p,与,a,相同,(2),int,*,p,;,定义,指针,变量,p,*,p,=10;,指针,p,所指,向,的变量,,,即,a,(3),&*,p,与&,a,相同,,,是,地址,*&,a,与,a,相同,,,是,变量,(4)(*,p)+,等价于,a+,将,p,所指,向,的变量值加1,*,p+,等价于,*(,p+),先取,*,p,,然后,p,自加,,此时,p,不再指向,a,说明,int,a=1,x,*p;,p=,x=*p+;,b,2,&,b,p2,*,p2,a,1,&,a,p1,*,p1,2,1,#include,int,main(void),int,a=1,b=2,t;,int,*p1,*p2;,p1=,printf,(,a=%d,b=%d,*p1=%d,*p2=%dn,a,b,*p1,*p2);,t=*p1;*p1=*p2;*p2=t;,printf,(,a=%d,b=%d,*p1=%d,*p2=%dn,a,b,*p1,*p2);,return 0;,例8-3 通过,指针,改变,变量的值,a=1,b=2,*p1=1,*p2=2,a=2,b=1,*p1=2,*p2=1,/,2、赋值运算,a,3,&,a,p1,&,a,p2,*,p1,*p2,int,a=3,*p1,*p2;,p1=,把,a,的地址赋给,p1,,即,p1,指向,a,p2=p1;,p2,也指向,a,相同类型的指针才能相互赋值,/,b,4,&,b,p2,*,p2,a,2,&,a,p1,*,p1,6,c,&,a,&,c,例8-4,指针,赋值,int,main(void),int,a,b,c,*p1,*p2;,a=2;b=4;c=6;,p1=,printf,(,a=%d,b=%d,c=%d,*p1=%d,*p2=%dn,a,b,c,*p1,*p2);,p2=p1;p1=,printf,(,a=%d,b=%d,c=%d,*p1=%d,*p2=%dn,a,b,c,*p1,*p2);,return 0;,*,p2,*,p1,a=2;b=4;c=6;*p1=2,*p2=4,a=2;b=4;c=6;*p1=6,*p2=2,/,例8-5,int,main(void),int,a=1,b=2;,int,*p1=,printf,(a=%d,b=%d,*p1=%d,*p2=%dn,a,b,*p1,*p2);,pt=p1;p1=p2;p2=pt;,printf,(“a=%d,b=%d,*p1=%d,*p2=%dn”,a,b,*p1,*p2);,return 0;,8.1.5,指针,变量,的,初始化,p1,b,2,&,b,p2,*,p2,a,1,&,a,*,p1,pt,b,2,&,a,p2,*,p1,a,1,&,b,p1,*,p2,pt,&,a,a=1;b=2;*p1=1,*p2=2,a=1;b=2;*p1=2,*p2=1,/,对指针的操作,/,对指针所指向变量的操作,*,p1,和*,p2,的值都由 1 和 2 变成了 2 和 1,(1)直接改变指针的值,(2)改变指针所指变量的值,p1,b,2,&,b,p2,*,p2,a,1,&,a,*,p1,a,p1,b,2,&,a,p2,*,p1,1,&,b,*,p2,p1,b,1,&,b,p2,*,p2,a,2,&,a,*,p1,/,8.2,狸猫换太子,一个关于发生在北宋年间变量替换的故事,关键点分析,真宗和李玉未出生的孩子:小王子,刘娥的阴谋:用狸猫替换掉孩子,筹备工作:设计两套替换行动方案,实施结果:行动一失败,行动二成功,/,int,main(void),int,baby=,PRINCE;,/*,baby,代表孩子,刚出生时是王子,*/,printf(before,change,baby is);,display,(baby);,replace1,(baby);/*,实施狸猫换太子第一次行动,*/,printf(n,);,printf(after,first action,baby is);,display,(,baby);,replace2,(/*,实施狸猫换太子第二次行动,*/,printf(n,);,printf(after,second action,baby is);,display,(baby);,return 0;,例8-6 指针作为函数参数模拟狸猫换太子,#define,CIVET,0,定义狸猫值为,0,#,define,PRINCE,1,定义王子值为,1,void,replace1,(int baby),baby=CIVET;,void,replace2,(int*baby),*baby=CIVET;,void,display,(int,who),if(who=CIVET),printf,(,狸猫,);,else if(who=PRINCE),printf,(,王子,);,before change,baby is,王子,after first action,baby is,王子,after second action,baby is,狸猫,8.2.2,指针,作为函数的参数,函数参数包括实参和形参,两者的类型要一致,可以是指针类型。,如果,实参,是某个变量的,地址,,相应的,形参,就是,指针,。,int,main(void),int,a=1,b=2;,int,*pa=&a,*,pb,=,void swap1(int x,int,y),swap2(,int,*,px,int,*,py,),swap3(,int,*,px,int,*,py,);,swap1(a,b);,printf,(“After calling swap1:a=%d b=%dn”,a,b);,a=1;b=2;,swap2(pa,pb,);,printf,(“After calling swap2:a=%d b=%dn”,a,b);,a=1;b=2;,swap3(pa,pb,);,printf,(“After calling swap3:a=%d b=%dn”,a,b);,return 0;,调用哪个函数,可以交换,main(),中变量,a,和,b,的值?,例8-7,swap1(),a,1,2,b,x,1,2,y,2,1,swap1(a,b);,void swap1(,int,x,int,y),int,t;,t=x;,x=y;,y=t;,/,例8-7,swap2(),swap2(&a,&b),;,void swap2(,int,*,px,int,*,py,),int,t;,t=*,px,;,*,px,=*,py,;,*,py,=t;,a,b,px,py,1,2,值传递,地,址未变,,但存放的变量的值改变了,2,1,/,例8-7,swap3(),swap3(&a,&b),;,void swap3(,int,*,px,int,*,py,),int,*pt;,pt=,px,;,px,=,py,;,py,=pt;,a,b,px,py,1,2,值传递,形参指针的改变不会影响实参,/,指针,作为函数参数的应用,swap2(,void swap2(,int,*,px,int,*,py,),int,t;,t=*,px,;,*,px,=*,py,;,*,py,=t;,要通过函数调用来改变主调函数中某个变量的值:,(1)在主调函数中,,将该变量的地址或者指向该变量的指针作为实参,(2)在被调函数中,,用指针类型形参接受该变量的地址,(3)在被调函数中,改变形参所指向变量的值,a,b,px,py,1,2,2,1,作业与实验,作业,习题,7,:,6,、,7,实验,习题,7,:,8,、,9,/,
展开阅读全文