收藏 分销(赏)

谭浩强c语言教程指针.ppt

上传人:精**** 文档编号:12293587 上传时间:2025-10-07 格式:PPT 页数:83 大小:315.50KB 下载积分:18 金币
下载 相关 举报
谭浩强c语言教程指针.ppt_第1页
第1页 / 共83页
谭浩强c语言教程指针.ppt_第2页
第2页 / 共83页


点击查看更多>>
资源描述
单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,谭浩强c语言教程 指针,C,程序的变量所存放的数据:,数值型数据:整数、实数,通过前面的学习,我们已知道:,字符型数据:字符、字符串,结构型数据:数组,占有一定长度的内存 单元,如,:int x;x,占二字节、二个单元,每一个变量都有一个地址,为无符号整数,它不同于一般的整数。,能否对地址运算?,能否用一个变量保存地址?,这些变量具有的性质:,问题:,7.1 指针变量的声明和初始化,一、数据在内存中的存放,设:,系统分配i,的起始地址为2000的单元,内存:,为一个连续编号(连续地址)且以一个单元为一个字节的连续存贮区。,若程序中定义了三个int,变量i,j,k,int i=5,j=5,k=10;,则:,j的起始地址有可能为为2002的单元,k,的起始地址有可能为2004的单元,2000,2001,2002,2003,2004,2005,3001,5,+5,10,2000,i,j,k,当程序中要用它们的值时:,y=i+j+k;,找到j,的地址2002,,将2002,20003中的数据5读出;,找到k的地址2004,,将2004,2005中的数据10读出。,分别,找到i的地址2000,,将2000,2001中的数据5读出;,则系统通过一张变量名与地址对应关系表:,直接访问,:,直接使用存放该数据的变量名。,间接访问,:,如果将某一变量的地址(如 i,的地址2000)存放到另一个变量x,则可通过x来存取i的值。,上述过程称为变量的“直接访问 ”,然后把这些数据进行算术运算。,i,相当于使用 5,使用变量,如:,用pi,pj,pk,来存放i,j,k的地址,2000,2002,2004,5,5,10,3001,3003,3005,3007,2000,2002,2004,pi,pj,pk,i,j,k,若要得到变量i,的值,可以先访问pi,得到i的地址,再通过该地址找到它i的值。,显然,pi,与i是通过i的地址联系起来的。,定义:,一个,变量的,地址称为该变量的指针,。因此,i的指针的值为2000。,如,:,pi就是指针变量。,而存放地址(指针)的变量叫做指针变量,。,二、指针变量的定义形式:,表示该变量为指向某类型变量的指针变量。,如:,int,p,;(p为指向整型变量的指针)char*s;(s为指向字符型变量的指针)float*t;(t为指向浮点型变量的指针),存储类型 类型名,变量名,CPU访问内存中数据的方式,CPU对变量的访问是根据内存单元的地址来进行的。访问的方式有:,(1)直接访问:,含义:已知变量的地址直接取地址单元内的值。,方法:通过变量名进行访问。,如:int x=2;printf(“%d”,x);,(2)间接访问,含义:通过存放变量地址的变量(指针变量)来访问目标单元的值。,方法:通过指针变量进行访问。,变量与地址,程序中,:int i;,float k;,内存中每个字节有一个编号-,地址,.,.,2000,2001,2002,2005,内存,0,2003,i,k,编译或函数调用时为其分配内存单元,变量,是对程序中数据,存储空间的抽象,指针的概念,.,.,2000,2004,2006,2005,整型变量,i,10,变量,i,_pointer,2001,2002,2003,指针:一个变量的地址,指针变量:专门存放变量地址的变量叫指针变量,2000,指针,指针变量,变量的,内容,变量的,地址,指针与指针变量,含义,含义:,取变量的地址,单目运算符,优先级:2,结合性:,自右向左,含义:,取指针所指向变量的内容,单目运算符,优先级:2,结合性:,自右向左,两者关系:互为,逆运算,理解,.,.,2000,2004,2006,2005,整型变量,i,10,变量,i,_pointer,2001,2002,2003,2000,指针变量,i_pointer,-指针变量,它的内容是地址量,*i_pointer,-指针的,目标变量,,它的内容是数据,&i_pointer,-指针变量占用内存的地址,2000,10,i_pointer,*i_pointer,&i_pointer,i,i_pointer&i&(*i_pointer),i *i_pointer *(&i),i_pointer,=,&i,=,&(*i_pointer),i,=,*i_pointer,=,*(&i),&与*运算符,直接访问:按变量地址存取变量值,间接访问:通过存放变量地址的变量去访问变量,例,i=,3,;,-,直接访问,指针变量,.,.,2000,2004,2006,2005,整型变量,i,10,变量,i,_pointer,2001,2002,2003,2000,3,例,*i_pointer=,20,;,-,间接访问,20,直接访问与间接访问,指针变量,.,.,2000,2004,2006,2005,整型变量,i,10,变量,i,_pointer,2001,2002,2003,2000,整型变量,k,例,k=i;,-,直接访问,k=*i_pointer;,-,间接访问,10,例,k=i;,k=*i_pointer;,例子图解,指针变量的引用,1、&:取地址运算符:用于,变量名,之前,表示该变量,的存储地址。,2、*:指针运算符(间接访问),用于,指针变量名,之前,获取该指针所指目标单元的值。,例:main(),int a,b,*point1,*point2;,a=100,b=200;point1=,printf(“%d,%dn”,a,*point2);,&和*两个运算符的优先级别是相同的,结合规律是右结合性:如:,若point1=,*,指针运算符,指针的运算,1、算术运算,含义:对于地址的运算,只能进行整型数据的加、减运算。,规则:指针变量,+,n 意味着将指针指向的当前变量向前或后的第n个变量单元。如:,2、关系运算,作用:用于识别目标变量在内存中的前后位置。,用法:int i,j;,int*p1=,p1p2 用于识别变量i,j在内存的排列顺序。,3、赋值运算,作用:对指针变量的赋值运算,将改变指针变量的指向,4、,举例:,i,j,p1,p2,1000,1002,2000,2002,2004,地址,k,j,i,p=&i,int i,j,k;,int*p=(p=2000),p+;(p=2002),p+;(p=2004),p-;(p=2002),小结:,指针变量的算术运算结果是改变指针目标的指向;,指针变量算术运算的过程;,p,新,=p,原值,+n*sizeof(类型),提供指针的目的:,使访问者与访问对象相隔离,改进对成批数据的访问速度,2000,2002,地址,j,i,p=&i,例:,int i=1,j=2;,int*p;,p=,*p=10;printf(“%d”,*p);,p=,要点:,应随时了解指针变量的目标指向;,不允许直接对指针变量赋常量值。,如:int*point;,point=1000;(,),只能给指针变量一个具有,地址属性的值,(,数据或变量)。,例:分析下面程序的功能.,main(),int*p1,*p2,*p,a,b;,scanf(“%d,%d”,p1=,if(ay?x:y;,return(z);,例 比较两个数并输出大者,main(),int a,b,c;,scanf(%d,%d,c=,max(a,b);,printf(Max is%d,c);,max(,int x,int y,),int z;,z=xy?x:y;,return(z);,形参,实参,p,2,=p;,main(),int a,b;,int,x,1,x,2,;,scanf(%d,%d,x,1,=,x,2,=,swap(x,1,x,2,);,printf(a=%d,b=%d n,a,b);,程序运行结果:,输入,:,10,20,输出,:,a=20,b=10,例:,swap(p,1,p,2,),int,p,1,p,2,;,int p;,p=,p,1,;,p,1,=,p,2,指针变量:,(实参),指针变量:,(形参),10,20,a,b,&a,p,1,p,2,x,1,x,2,&b,程序中,实参与形参共用同一个内存单元,通过修改地址所指的值来交换数据:,20,10,a,b,&a,p,1,p,2,x,1,x,2,&b,指针变量:,(实参),指针变量:,(形参),1.注意函数中p,为普通变量,并非地址量;,2.如果swap,函数中的交换语句改为:,swap(p,1,p,2,)int,p,1,p,2,;int,p;p=p,1,;p,1,=p,2,;p,2,=p;,则仅将p,1,p,2,的指向改变,函数返回后,p,1,p,2,释放,a、b中的内容依然未改变。,调用函数时:,&a,x,1,x,2,&b,实参,10,20,a,b,p,1,p,2,形参,sway(p,1,p,2,),int p,1,p,2,;,int p;,p=p,1,;,p,1,=p,2,;,p,2,=p;,3.不用地址量作参数,不能实现交换,即:,4.结论:,若要使变量的值通过函数调用而发生改变,则形参必须是指针型,实参为地址量,&,或指针型。,另,:全局变量和数组名作为参数也可改变变量的值.,传引用(传址)调用,传引用(传址)调用,把实参,形参后,传递,形参变量和实参变量共同内存地址。,地址传递:数组名和指针(共用内存单元),特点:,形参变量的值的变化会影响实参的值的改变。,例a:分析下面的程序写出结果,swap(int*x,int*y),int*t;,t=x,x=y,y=t;,printf(“%d,%dn”,*x,*y);,main(),int a=3,b=5;,swap(,printf(“%d,%dn”,a,b);,运行结果为:5,3,3,5,例b:分析下面的程序写出结果,swap(int a,int b),int t;,t=a,a=b,b=t;,printf(“%d,%dn”,a,b);,main(),int a=3,b=5;,swap(a,b);,printf(“%d,%dn”,a,b);,运行结果:5,3,3,5,例c:分析下面的程序写出结果,swap(int*x,int*y),int t;,t=*x,*x=*y,*y=t;,printf(“%d,%dn”,*x,*y);,main(),int a=3,b=5;,swap(,printf(“%d,%dn”,a,b);,运行结果:5,3,5,3,例:,输入a、b、c三个整数,按大小顺序输出,。,swap(int*x,int*y),int t;,t=*x,*x=*y,*y=t;,main(),int a,b,c,*p1,*p2,*p3;,scanf(“%d,%d,%d”,运行情况:,p1=,输入:,9,0,10,exchange(p1,p2,p3);,输出:,10,9,0,printf(“%d,%d,%dn”,a,b,c);,exchange(q1,q2,q3),int*q1,*q2,*q3;,if(*q1*q2)swap(q1,q2);,if(*q1*q3)swap(q1,q3);,if(*q2*q3)swap(q2,q3);,7.8 指针和数组的关系,一个变量的地址为该变量的指针。当用一个变量来存放该地址(指针)时,称为指针变量。,一个数组元素相当于一个简单变量。于是,亦可用一个指针变量来指向数组元素。,不同之处:,数组元素连续地占用内存单元,则当一个元素的指针已知时,其它元素的指针亦可知道。,定义方法与简单变量指针定义相同,但引用略有不同,例:,int a10;,int,p;,/*,定义*/,p=,/*将a,的第1个元素的地址赋给p*/,一、数组元素指针变量的定义与引用,指针也可用下标表示。,如:,P2,表示引用数组元素a2,C,语言规定,:,数组a的首地址即用&a0表示,亦可用a表示,所以,:p=和 p=a等价,例,:,#include,main(),int a1=123,a2=234,a3=345;,int*p1,*p2,*p3;,int as3=1,2,3,*ps;,p1=,p2=p1+1;,p3=p2+1;,printf(p1=%ldn p2=%ldn p3=%ldn,p1,p2,p3);,printf(*p1=%dn *p2=%dn *p3=%dn,*p1,*p2,*p3);,ps=as;,printf(ps0=%dn ps1=%dn ps2=%dn,ps0,ps1,ps2);,运行结果:,p1=262737918,p2=262737920,p3=262737922,*p1=123,*p2=0,*p3=320,ps0=1,ps1=2,ps2=3,地址,a1,的值,系统给定的值,数组元素地址,定义方法,一、定义方法:,与一般指针变量的定义方法相同。,如:,int a10,*p1,*p2;,p1=a;,p2=,注:p1,为,指向数组,的指针,p2为,指向数组,元素的指针,二、要点:,在定义指针变量时可以直接赋初值。,如:,int a10,*p1=a,*p2=,a0,a,a1,a2,a9,p1=a,ai,p2,a0,a1,a2,a3,a9,.,a,a+9,a+1,a+2,地址,元素,下标法,a0,a1,a2,a9,a0,a1,a2,a3,a9,.,p,p+9,p+1,p+2,地址,元素,指针法,*p,*(p+1),*(p+2),*(p+9),变址运算符,地址法,a,i,*(a+i),ai,pi,*(p+i),*(a+i),*a,*(a+1),*(a+2),*(a+9),p0,p1,p2,p9,利用指针访问数组的几种方法,一、功能:,引用数组元素可以用下标法,还可以用指针法。使用指针方法能使目标程序的质量占内存少、运行速度快。,二、基本方法,1、将指针指向数组中的某个元素;,2、利用,*(p,+,n),获得数组元素的值。,如:int a9=0,1,2,3;,int*p=a;,printf(“%d”,*p);,printf(“%d”,*p+);,printf(“%d”,*p-);,3、例:,三、,要点:,a0,*(p+n-1),a,a1,a2,an-1,p+,p+,p=a,ai,p+i或a+i,p+n-1,*(p+i),或,pi,例:输出数组的全部元素。,方法一:下标法,main(),int a10;,int i;,for(i=0;i10;i+),scanf(“%d”,printf(“n”);,for(i=0;i10;i+),printf(“%d,”,ai);,方法二:地址法(通过数组名计算数组元素地址,找出元素的值),main(),int a10;,int i;,for(i=0;i10;i+),scanf(“%d”,printf(“n”);,for(i=0;i10;i+),printf(“%d,”,*(a+i);,例:输出数组的全部元素。,方法三:指针法(指针变量指向数组元素),main(),int a10;,int*p,i;,for(i=0;i10;i+),scanf(“%d”,printf(“n”);,for(p=a;pa+10;p+),printf(“%d,”,*p);,三种方法的比较:,方法1与方法2的执行效率相同,都是先计算数组元素的地址,再访问数组元素的值,费时。,方法3利用指针变量直接访问数组元素的值,不必计算数组元素的地址,故执行效率高。,下标法直观,指针法与地址法不够直观。,例:下面的程序的输出结果是什么?,#include,int a=2,4,6,8;,main(),int i,*p=a;,for(i=0;i4;i+),ai=*p+;,printf(“%dn”,a2);,运行结果为:6,问题:ai=*p+改为:(i3),ai=*+p,若有:float*t;且:*t=3.6;,设t的地址为2000,,则t+1,2004,例:,若有:int*p;且:*p=5;,设p的地址为2000,,则p+1,2002,若有:char*s;且:*s=a;,设s的地址为2000,,则s+1,2001,一、指针移动,二、关于指针的其它运算,p+/p,的作用:,指针运算符,与+,同级,且自右至左。,而 p 相当于p=p 1,即指向a4,若有,:int a10,*p;,p=,则:p+相当于p=p+1,即指向a6,(,p)+,或(,p),(,p)+:,将p指向的变量的值自增1;,(,p):,将p指向的变量的值自减1。,p+,相当于,(p+),(,结合方向:自右向左),若p=&a0,则*(p+)取出a0的值;,(+p):,首先使p,p+1,p,指向a1,,(+p),取出a1的值,。,p+与,(+p),的含义,例,:/*-exp.c-*/,#include,main(),int a5=11,22,33,44,55,*p;,p=,printf(*p+=%dn,*p+);,printf(*p=%dn,*p);,printf(*p)+=%dn,(*p)+);,printf(*p=%dn,*p);,运行结果:,*p+=11,*p=22,(*p)+=22,*p=23,取出a0,的值,指向a1,的值,先取a1,的值,使a1,的值增加1,例:下面的程序的输出结果是什么?,演示!,main(),int a10;,int*p,i;,p=a;,for(i=0;i10;i+),scanf(“%d”,p+);/p位置?每数回车!,p=a;/再次回到原地址,printf(“n”);,for(i=0;i10;i+,p+),printf(“%d,”,*p);,例:下面的程序的输出结果是什么?,演示!,void fun(int*p,int n),while(n-),(*p)+;,p+;,main(),static int a=0,1,2,3,4,5,6,7,8,9;,int i;,fun(a,10);,for(i=0;i10;i+),printf(“%d,”,ai);,例:设计一函数,找出一维数组中的最大最小值,void max_min(int a,int n,int*pmax,int*pmin),int i;,*pmax=*pmin=a0;,for(i=1;in;i+),if(*pmax ai)*pmin=ai;,main(),static int arr10=1,0,2,3,-8,5,15,7,8,9;,int max,min;,max_min(arr,10,printf(“max=%d,min=%dn”,max,min);,字符和字符串处理函数的主要用途:,设计编辑器,设计字处理器,设计排版文字处理器,设计转换程序,字符和字符串,一、字符串的特点,回顾:,char ch;,ch,为字符变量,char a10;,a,为字符数组,字符串是一个特殊的数组,在数组中有一个空字符0来作为字符数组的结束,通过访问数组名来访问字符串,字符串可用指向字符串的指针来访问,二、关于字符、字符数组、字符串指针的几种说明,char ch;,ch,为字符变量,char a=s,t,u,d,e,n,t;,a,为字符数组长度为7,char b=student;,b,为字符数组,长度为8,b,也可作为字符串名,char*ptr=student;,ptr 为指向字符或字符串的指针,三、关于字符串指针,例,:#include main()char,p;char s=I am a student!;p=s;printf(p=%s,p);,形式,char,标识符;,运行结果为:,p=I am a student!,1.字符串指针的定义,表示p为指针变量,可指向一个字符串的首地址。,如:,char*p;,可以在定义的时候赋初值:,main()char,p=I am a student!;,或者:,main(),char,p;,p=I am a student!;,则:,p代表 I,(p+3)代表m,p,I,a,m,a,s,t,u,d,e,n,d,0,例,:将字符串a复制到字符串b,1)main(),char a =I am a teacher!;,char b20;,int i;,for(i=0;,(a+i)!=0;i+),(b+i)=,(a+i);,(b+i)=0;,1),用字符数组实现,printf(string a is:%sn,a);,printf(string b is:);,for(i=0;bi=0;i+),printf(%c,bi);,printf(n);,等价于:,printf(string b is:%sn,b);,string a is:I am a teacher!,string b is:I am a teacher!,运行情况如下:,main(),char a=I am a teacher!;,char b20,p,1,p,2,;,p,1,=a;p,2,=b;,for(;,p,1,!=0;p,1,+,p,2,+),p,2,=,p,1,;,p,2,=0;,printf(string a is:%sn,p1);,printf(string b is:%sn,p2);,2)用指针变量实现,运行情况如下:,string a is:I am a teacher!,string b is:I am a teacher!,1、字符串指针的作用:,可以用来描述一个字符串。,方法:char*str=“I am a student.”;,2、物理含义:,不是将字符串的内容赋值给指针变量,而是将其起始地址赋给它。,char*str;,str=“I am a student.”;,3、应用:,利用字符串的指针变量对字符串进行输入与输出。,puts(),gets(),scanf,(),printf,(),的%,s,输出格式。,例:,总结:字符串指针,例exp1:分析下面的程序,演示,main(),char arr=“ABCDE”;,char*ptr;,for(ptr=arr;ptrarr+5;ptr+),printf(“%sn”,ptr);,运行结果为:ABCDE,BCDE,CDE,DE E,例exp2:有以下的程序,输出结果为:,演示,main()char*p1=“programming”,*p2=“language”;,int i;,for(i=0;i7;i+),if(*(p1+i)=*(p2+i),printf(“%c”,*(p1+i);,结果:ga,字符串指针作函数参数,例:,用函数调用实现字符串的复制,与数值变量指针一样,字符串指针,字符串数组均可作为函数参数,作用:,可在函数中改变实参内容。,toi=fromi;i+,toi=0;,main(),char a=I am a teacher;,char b=You are a student;,printf(string_a=%sn string_b=%sn,a,b);,copy_string(a,b);,printf(n string_a=%sn string_b=%sn,a,b),void copy_string(from,to),char from,to;,int i=0;,while(fromi!=0),方法,:,(1)字符数组作参数,运行结果,:,string_a=I am a teacher,string_b=You are a student,string_a=I am a teacher,string_b=I am a teacher,可以在main中使用字符串指针:,char,a=I am a teacher.;,char,b=You are a student.,但以字符串的方式输出b中内容时,遇到第一个0时结束。,实际上,数组b,中的内容为:,I a m a t e a c h e r 0 n t 0,void copy_string(from,to),char,from,to;,for(;,from!=0;from+,to+),to=,from;,to=0;,或:,将for,改用while,(2)形参用字符指针变量,while(,from!=0 ),to=,from;to+;,from+;,或:,while(,to=,from)!=0)from+;to+;,或:,while(,to+=,from+)!=0);,实际上0,的ASCII码为0,故可将,while(,to+=,from+)!=0),简化为:,while(,to+=,from+),传引用调用时,函数的实参、形参调用的四种情况,实参 形参,数组名 数组名,数组名 指针型,指针型 指针型 ,指针型 数组名,小结:,1.字符数组由若干个元素组成,每个元素存放一个字符,而字符指针存放的地址(当处理字符串时存放的是字符串的地址);,2.赋,初值,方式不同;,static char a=“I am a student.”;,char*str=“I love China.”;,3.,赋值,方式不同;,1)对于字符数组赋值,不能,使用以下的方法:,char str10;,str=“book”;,2)对于字符类型的指针变量,可以,使用以下的方法:,char*str;,str=“This is a book.”;,字符指针与字符数组的区别,4.字符指针变量在使用之前必须初始化,即使其指向一个具体的存储单元。如:,char str;,scanf(“%s”,str);是正确的,而 char*str;,scanf(“%s”,str);将是十分错误的。,应为:char*a,str;,a=str;,scanf(“%s”,a);,5.指向字符类型的指针变量可以用指针的形式表示,也可以用下标的形式表示。,例:,例:分析以下的程序,main()char*str=“I am a student.”;,str=str+7;,printf(“%sn”,str);,for(;*str;printf(“%c”,*str+);,printf(“n”);,运行结果:student.,student.,例:分析以下的程序,main()char*str=“I am a student.”;,int i;,str=str+7;,printf(“%sn”,str);,for(i=0;i0;i-),str2*i=stri;,str2*i-1=;,printf(“n The result is:n%s”,str);,写出运行结果:,#include,main(),static char s=“This Is a String”;,fun(s,i);,puts(s);,fun(s,T);,puts(s);,void fun(char*p,char c),for(;*p!=0;p+),if(*p=c),if(c=A,else*p=c-a+A;,作业,为了实现对字符串的操作,可以定义一个字符数组,也可以定义一个字符指针。通过指针指向访问字符,main(),char string=“C Language”;,char*p;,p=string;,printf(“%sn”,string);,printf(“%sn”,p);,运行结果:C Language,C Language,补充1:,用“%c”输出:,for(p=string;*p!=0;p+),printf(“%c”,*p);,用“%s”输出:,char string=“C Language”;,char*p;,p=string;,printf(“%sn”,string);,printf(“%sn”,p),从给定的地址开始逐个字符输出,直到,遇到“0”为止。,补充2:,例:一行文字,要求删除指定字符。,“I have 50 Yuan”,删除变为“I have 5 Yuan”,main(),char*p=“I have 50 Yuan”,a20,x;,int i=0;x=0;,for(;*p!=0;p+),if(*p!=x)ai+=*p;,ai=0;,printf(“The new string is:%sn”,a);,补充3:,
展开阅读全文

开通  VIP会员、SVIP会员  优惠大
下载10份以上建议开通VIP会员
下载20份以上建议开通SVIP会员


开通VIP      成为共赢上传

当前位置:首页 > 包罗万象 > 大杂烩

移动网页_全站_页脚广告1

关于我们      便捷服务       自信AI       AI导航        抽奖活动

©2010-2026 宁波自信网络信息技术有限公司  版权所有

客服电话:0574-28810668  投诉电话:18658249818

gongan.png浙公网安备33021202000488号   

icp.png浙ICP备2021020529号-1  |  浙B2-20240490  

关注我们 :微信公众号    抖音    微博    LOFTER 

客服