您好,欢迎访问三七文档
第9章指针特点能直接对内存地址操作,使用灵活实现动态存储管理可以使程序简洁、紧凑、高效用间接访问的方式改变数据的逻辑顺序调用函数时可实现变量的引用传递地址和指针的概念变量的地址和变量的值inti=3;floatj=6;doublek=9;36.09.0变量i变量j变量k2200220622022214程序中定义的变量,系统根据它的类型给它分配一定长度的内存单元,该内存单元的起始地址即为变量的地址。该内存单元的内容就是变量的值。直接访问和间接访问直接访问:用变量名直接从它对应的地址存取内容。如:intx=5,y=8,z=0;z=x+y;580变量x变量y变量z22002202220413直接从x和y对应的地址2200和2202取出内容5和8然后相加将结果13存入变量z对应的地址2204的单元中。间接访问定义一个存放地址的变量p(p的地址1500),将x的地址2200存放在变量p中。通过变量p取出地址2200,再按此地址存取其中的内容,就间接的完成了对x的存取。当p的内容改为2202时,通过变量p取出地址2202,再按此地址,存取的就是变量y的内容。p就是指针变量580变量x变量y变量z22002202220422001500变量p2202指针变量的定义一般形式:基类型名*指针变量名说明:基类型名:指针变量所指向的变量的类型名称指针变量名:所定义的指针变量的名称*:表示它后面的变量名是指针类型功能:(1)定义该指针变量名为指向基类型的指针变量,为该变量分配存储单元,其长度等于存储地址的字节数。(2)基类型确定用指针变量“间接”存取数据的存储单元个数和存储形式。该变量只能指向基类型数据。指针变量的初始化用=&变量名来给指针变量赋初值。选项中的变量名必须是已定义过的,其类型必须与基类型一致。表示将它对应的地址值赋给所定义的指针变量。例如:intx,p=&x;intx,*p=&x;intx;float*p=&x;可以用赋值语句给指针变量赋值:floaty,*py;py=&y;指针变量的引用引用指针变量的指针值与引用其它类型的变量一样直接用它的变量名引用指针变量所指向的变量时,用“*指针变量名”注意:①指针变量的值与它所指向变量的值之间的差别②指针变量只有正确赋值后才能通过它访问指向的变量。xintx;pp=&x;&xint*p;*p*p=5;5指针变量的运算1.&:取地址运算符,取右边变量的地址2.*:指向运算符(间接访问运算符),访问指针变量右边所指向的变量。&a是变量a的地址*p是指针变量p指向的变量。说明:“&”和“*”都是单目运算符,它们的优先级相同,按自右而左方向结合。如果已定义floata,*p=&a;则*p是变量a&*p是变量a的地址p&*p等价于p而&a是变量a的地址p*&a是p所指向的变量a*&a等价于a注意(1).指针变量定义和引用指向变量的“*”含义有差别。(2).不能引用没有赋值的指针变量,不要误认为p定义后变量*p就已存在,必须给p正确赋值后,变量*p才存在。(3).p=&a;是给指针变量p赋值,*p=3;是给p指向的变量赋值。两者含义完全不同。(4).给指针变量赋值必须用同类型的指针。(5).指针变量只存放地址,地址值是无符号整数,但不能直接用整型量(或其它非地址量)赋值给指针变量。int*p1=2200;给变量赋值的两种方法1.直接访问用变量名如:inti;i=5;2.间接访问通过指向变量i的地址的指针变量p赋值如:inti,*p;p=&i;*p=5;取地址运算符&和指向运算符*的应用main(){intm,n;int*p=&m,*q=&n;printf(Inputm,n:);scanf(%d%d,p,&n);printf(m=%d&m=%X\n,m,&m);printf(*p=%dp=%X\n,*p,p);printf(n=%d&n=%X\n,n,&n);printf(*q=%dq=%X\n,*q,q);}运行结果:Inputm,n:123456m=123&m=FFD6*p=123p=FFD6n=456&n=FFD8*q=456q=FFD8{intx,y;xyp1pp2int*p,*p1,*p2;p1=&x;p2=&y;&x&y86x=8;y=6;printf(min=%d,max=%d\n,*p1,*p2);}p1=p2;&yif(xy){p=p1;&xp2=p;}&xmain()运行结果:min=6,max=8例:通过交换指针变量值按大小顺序输出指针变量作为函数的参数以指针类型为函数的参数,作用是将变量的地址传入函数。intx,y;int*pt1;*pt2;x=8;y=6;pt1=&x;pt2=&y;if(xy)swap(pt1,pt2);printf(x=%d,y=%d\n,x,y);swap(int*p1,int*p2)p=*p1;*p1=*p2;*p2=p;{intp;p8pt1pt2xy{}main(){}&x&yp1p2&x&y8668运行结果:x=6,y=8intx,y;int*pt1;*pt2;x=8;y=6;pt1=&x;pt2=&y;if(xy)swap(pt1,pt2);swap(int*p1,int*p2)p=*p1;*p1=*p2;*p2=p;{intp;printf(x=%d,y=%d\n,x,y);指针与数组C语言中规定数组名是指针类型的符号常量,该符号常量值等于数组首元素的地址(简称数组首地址),它的类型是指向数组元素的指针类型。即数组名是指向该数组首元素的指针常量。指向数组元素的指针1.定义指向数组元素的指针变量定义指向数组元素的指针变量与定义指向变量的指针变量的方法相同.如:inta[10];int*p;p=&a[0];由于数组名是指向0号元素的指针类型符号常量,所以a与&a[0]相等。p=&a[0];p=a;两句等价p=a不是把a的各元素赋给p注意数组名与指针变量的区别指针运算指针变量可以加减一个整数,两个同类型指针可以相减得到一个整数。指针变量每增减1,地址值增减量等于所指向的变量类型的字节数sizeof(type),将它称作地址步进单位d。当指针变量指向数组元素时,指针变量每加减1,表示指针前后移动1个元素,地址值增减d。如:inta[10],*p;p=a;p++;p+=3;注意:指针变量的运算顺序。++*p,*p++,*(++p),(*p)++四者之间的差别:++*p先给p指向的变量加1,然后取其值(*p)++先取p指向的变量值,然后该变量值加1*p++取p所指向变量的值,然后p增1*++pP先增1,然后取p所指向变量的值main(){inta[4]={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通过指针引用数组元素在inta[10],*p=a;定义的情况下:(1)p+i或a+i就是a[i]的地址。都要进行a+i×d的运算。(2)*(p+i)或*(a+i)就是p+i或a+i所指向的数组元素a[i]。数组元素中的“[]”是变址运算符,相当于*(+),a[i]相当于*(a+i)。(3)指向数组元素的指针变量也可带下标,如p[i]与*(p+i)等价。所以,a[i],*(a+i),p[i],*(p+i)四种表示法全部等价。(4)注意p与a的差别,p是变量a是符号常量,不能给a赋值,语句a=p;a++;都是错的。p&a[0]a[9]a[1]a[2]a[i]a[0]p+1,a+1p+2,a+2p+i,a+ip+9,a+9a引用数组元素可用:1)下标法,如a[i],p[i]。2)指针法,如*(p+i)或*(a+i),其中p是指向数组a的元素的指针变量。main(){inta[10];int*p,i;for(p=a;p(a+10);p++)scanf(%d,p);printf(\n);for(i=0;i10;i++)printf(%d,a[i]);}①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);例.输入/输出数组全部元素用字符型指针访问字符数组和字符串【例9.5】用字符型数组名和字符指针变量两种方法整体输入/输出字符串。main(){chars[81]=Hello!,*p=s;char*ps=Welcometoyou!;printf(%s\n,s);printf(%s\n,ps);gets(s);printf(%s\n,s);gets(p);printf(%s\n,s);}字符指针变量和字符数组的区别(1)存储的内容不同:字符数组存储着字符串的内容,而字符指针变量存放的是字符串首元素的地址,不是它的内容。(2)分配的内存单元不同:字符数组分配一段有确定地址的内存。而指针变量只分配存放地址的内存单元,该指针变量可以指向一个字符型数据,但若未赋初值,则它并未指向一个明确的地址。此时它指向的变量并不存在。(3)赋值方法不同:对字符数组只能在定义时整体赋初值,不能用赋值语句整体赋值。赋值语句只能对各个元素分开赋值。如:chars[16];s=Iamastudent.;chars[16]=Iamastudent.;对字符指针变量,可以采用下面方法赋值:char*p;p=Iamastudent.;(4)指针变量的值是可以改变的,字符数组名是地址常量其值是不能改变的。数组或指针变量作函数参数如:main()f(inta[],intn){intarray[10];{......f(array,10)}...}由于数组名代表首地址,能接收并存放地址值的只能是指针变量。故编译系统将形参数组名作为指针变量来处理。例中函数首部f(inta[],intn)可写成f(int*a,intn)两种完全等价。归纳起来,如果有一个数组,想在被调用的函数中改变其元素的值,实参与形参的对应关系有以下四种:(1).实参和形参都用数组名。(2).实参用数组名,形参用指针变量。(3).实参用指针变量,形参用数组名。(4).实参和形参都用指针变量。实质都是地址值的传递【例9.7】通过调用函数,将整型数组的所有元素加10。参数传递用四种方法实现。voidadd(intb[],intn){inti;for(i=0;in;i++)b[i]+=10;}main(){inti,a[10]={1,2,3,4,5,6,7,8,9,10};add(a,10);for(i=0;i10;i++)printf(%4d,a[i]);}voidadd(int*p,intn){int*pend=p+n;for(;ppend;p++)*p+=10;}main(){inti,a[10]={1,2,3,4,5,6,7,8,9,10};add(a,10);for(i=0;i10;i++)printf(%4d,a[i]);}voidadd(intb[],intn){inti;for(i=0;in;i++)b[i]+=10;}main(){inti,a[10]={1,2,3,4,5,6,7,8,9,10};int*q=a;add(q,10);for(i=0;i10;i++)printf(%4d,a[i]);}voidadd(int*p,intn){int*pend=p+n;for(;ppend;p++)*p+=10;}main(){inti,a[10]={1,2,3,4,5,6,7,8,9,10};int*q=a;add(q,10);for(i=0;i10;i++)printf(%4d,a[i]);}用字符数组或指针做函数参数传递字符串将字符串从一个函数传递到另一个函数,可以用地址传递的方法,即用字符数组名或用字符指针变量作参数。在被调用的函数中可以改变字符串中的内容
本文标题:c语言指针课件
链接地址:https://www.777doc.com/doc-3675846 .html