《华中科技大学光电子学院C语言第七章.ppt》由会员分享,可在线阅读,更多相关《华中科技大学光电子学院C语言第七章.ppt(48页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、第七章第七章指指针针1.指针与数组的关系指针与数组的关系2.指针与函数的关系指针与函数的关系1.指针及定义指针及定义一一.指针变量的定义指针变量的定义指针变量指针变量:存放对象地址的变量存放对象地址的变量.指针变量定义的基本形式指针变量定义的基本形式:类型说明符类型说明符*变量名变量名;例例:int*pi,*pj;/*pi,pj指向整型变量的指针变量指向整型变量的指针变量*/float*p3;/*p3是指向浮点型变量的指针变量是指向浮点型变量的指针变量*/注注:1.定定义义指指针针变变量量的的物物理理意意义义:机机器器给给指指针针变变量量分分配配内内存存单元单元,此单元只能存放对象的地址此单元
2、只能存放对象的地址12.指针类型是指针所指对象的类型指针类型是指针所指对象的类型(指针本身没有类型指针本身没有类型)例例:int*fpi(),*a10,(*pa)10;/*复复杂杂变变量量的的指指针针*/fpi是是一一个个整整型型指指针针函函数数(函函数数返返回回值值是是指指向向int变变量量的的指指针针)a是含有是含有10个元素的整型指针数组个元素的整型指针数组(每个元素是一个指向每个元素是一个指向int变量的指针变量的指针)pa是指向含有是指向含有10个个int元素的数组的指针元素的数组的指针2二二.指指针针变变量量的的运算符运算符指针变量运算符指针变量运算符*:间接取对象的内容间接取对象
3、的内容&:取操作对象的地址取操作对象的地址(都都是是一一目目运运算算符符)例例:int*p,*p1,t,t1;p=&t;/*使使p指向指向t*/*等价于等价于p=&t;p1=p*/p1=&t;/*使使p1指向指向t*/t=4;t1=*p+3;/*间接取间接取p指的对象内容指的对象内容+3=t1,即即t1=7,等价于等价于t1=t+3*/*p=0;/*将将0送送p指向的指向的t单元中单元中,即即t=0*/3例例:inti,j,*p;1)i=123;2)p=&i;3)j=*p;但但:p=i;或或p=j;p=123都都是是错错误误的的,不不能能将将常常量量或或变变量量的的内容值送指针变量内容值送指针
4、变量.注注:1)&变变量量名名:包包括括基基本本类类型型的的变变量量,数数组组元元素素,结结构构变变量量或或结结构构的的成成员员.不不能能作作用用于于数数组组名名.,常常量量,非非左左值值表达式或寄存器变量表达式或寄存器变量.例例:doubler,a20;inti;registerintk;表达式表达式:&r,&a0,&a1是正确的,是正确的,&(2*r),&a,&k是非法的是非法的42).*与与&是互逆的运算符是互逆的运算符charc,*pc;pc=&c;*(&c)=a;/*间接寻址间接寻址pc*/*pc=a;/*间接寻址间接寻址.访问访问c*/c=a;/*直接寻址直接寻址,访问访问c*/三
5、三.指针运算指针运算1.赋值运算赋值运算1).同同类类型型的的指指针针变变量量可可以以相相互互赋赋值值,(指指向向同同一一类类型型的的对对象象)int*p1,*p2,a;p1=&a;p2=p1;*p1=5;2).常数常数0(NULL)可以赋给任何类型的指针变量可以赋给任何类型的指针变量p1=0;p2=0;3).不同类型的指针变量之间赋值必须采用类型强制符不同类型的指针变量之间赋值必须采用类型强制符来转换来转换(不能自动类型转换不能自动类型转换,void指针除外指针除外)如如:int*pi;charbuf100,*bufp=buf;/*数组名作为地址常数赋数组名作为地址常数赋给指针变量给指针变量
6、bufp*/pi=(int*)bufp;4)两种特殊指针两种特殊指针:void指针和指针和NULL指针指针void指针指针:指向空值类型的指针变量指向空值类型的指针变量:可以与任何类型可以与任何类型指针变量相互赋值指针变量相互赋值(不需要强制类型转换不需要强制类型转换)如如:int*p;void*p1;p=p1;p1=p;NULL指针指针:具有整数具有整数0值的指针值的指针:即不指向任何对即不指向任何对象的指针象的指针NULL符号常量符号常量:在在有定义有定义:或用或用#defineNULL0定义定义void*f();/*f是是无无参参数数的的指指针针函函数数*/void*pa=&x1,&x2
7、,&x3,&x4;7例例:main()int*p1,*p2,*p,a,b;scanf(“%d%d”,&a,&b);p1=&a;p2=&b;if(a,=,q若值为非若值为非0,则,则p所指的数据位于所指的数据位于q所指的数据所指的数据之前,反之为之前,反之为0指指针针变变量量不不能能与与常常量量比比较较,但但常常量量0(NULL)可可与与任任何何类类型的指针变量作型的指针变量作=或或!=的比较的比较102.指针与数组指针与数组指针与数组有密切关系:任何由数组下标完成的操作,指针与数组有密切关系:任何由数组下标完成的操作,都可由指针实现都可由指针实现.一一维数组的指针表示一一维数组的指针表示例例:
8、inta10,*pa;pa=&a0;pa=a;(或或pa=a+0)指针指向数组的首址指针指向数组的首址规定规定:pa+1指向指向a+1&a1第第1个元素个元素pa+2指向指向a+2&a2第第2个元素个元素pa+i指向指向a+i&ai第第i个元素个元素故故:*(pa+i)或或*(a+i)就是就是ai的内容的内容11注注:1)当指针变量指向数组首址后当指针变量指向数组首址后,以下标为以下标为i的数组元素引用的数组元素引用的方法有的方法有3种种*(指针变量指针变量+i),*(数组名数组名+i),数组名数组名i指针法指针法数组元素法数组元素法2)数组名与指针之间有区别数组名与指针之间有区别:指针是变量
9、指针是变量;数组名是地址常量数组名是地址常量如如:pa=a;pa+;是有意义的操作是有意义的操作a=pa;a+;pa=&a;a=a+1;都是非法的都是非法的.访问一个数组元素访问一个数组元素:可用下标法:可用下标法:ai,也可用指针法也可用指针法:*(p+i)或或*(a+i)121).下标法下标法:main()inti,min,max,a10;for(i=0;i10;i+)scanf(“%d”,&ai);min=max=a0;for(i=1;imax)max=ai;elseif(aimin)min=ai;printf(“max=%d,min=%dn”,max,min);例例:求整型数组求整型数
10、组a10中的最大值和最小值中的最大值和最小值2)用数组名访问元素用数组名访问元素main()inti,min,max,a10;for(i=0;i10;i+)scanf(“%d”,a+i);min=max=*a;for(i=1;imax)max=*(a+i);elseif(*(a+i)min)min=*(a+i);printf(“max=%d,min=%dn”,max,min);3)用指针间接访问用指针间接访问main()int*p,min,max,a10;p=a;for(;p(a+10);p+)scanf(“%d”,p);min=max=*a;for(p=a+1;pmax)max=*p;els
11、eif(*pmin)min=*p;printf(“max=%d,min=%dn”,max,min);注注:1.指针变量的定义和没有指明长度的数组视为一样指针变量的定义和没有指明长度的数组视为一样例例:在函数定义中在函数定义中;参数说明参数说明:f(chars)f(char*s)2.在在C语言中语言中,只要出现未加下标的数组名只要出现未加下标的数组名,字符串常量名字符串常量名,结结构构名名,联联合合名名或或不不带带参参数数的的函函数数名名,都都可可以以解解释释成成指指针针.因此可同指针变量一样置初值因此可同指针变量一样置初值3.指针与字符串指针与字符串(字符数组字符数组)如如:chars=“It
12、sastring”;char*s=”Itsastring”;但有区别但有区别:如如:char*p;/*指向一个字符的指针变量指向一个字符的指针变量*/p=“Itsastring”/*指向字符串的串首址指向字符串的串首址*/scanf(“%s”,p);/*错错误误,没没有有为为p所所指指的的对象分配空间对象分配空间*/又如又如:chars;s=“Itsastring”;/*错误错误s为地址常量为地址常量*/例例:lenth(s)/*计算计算s的长度的长度*/chars;intn;for(n=0;sn!=0;n+);return(n);lenth(s)char*s;intn;for(n=0;*s+
13、!=0;n+);return(n);#includemain()staticchars1=”abcdef”;/*等等价价于于char*s1=“abcded”;*/intstring;string=lenth(s1);/*等等价价于于string=lenth(&s10);*/printf(“%dn”,string);例例:把字符串把字符串t复制到字符串复制到字符串s中的函数中的函数strcpy(s,t)用指针用指针strcpy(s,t)char*s,*t;while(*s+=*t+)!=0);用数组用数组strcpy(chars,chart)inti;for(i=0;(si+=ti)!=0;);
14、*(s+i+)=*(t+i)二二.指针与多维数组指针与多维数组1.二维数组元素的表示二维数组元素的表示例例:inta23=1,2,3,4,5,6;1)下标表示下标表示:元素的地址表示元素的地址表示:&aij(取地址取地址)元素的内容表示:元素的内容表示:aij2)元素的数组名表示元素的数组名表示例例:inta23=1,2,3,4,5,6;数组名数组名a被看成由元素被看成由元素a0,ai的一维数组的一维数组,但但a0又可看成包含又可看成包含3个元素个元素a00,a01,a02,一维数一维数组组a1又可看成包含又可看成包含3个元素个元素a10,a11,a12,一维数组一维数组即即:根据根据C语言规
15、定语言规定:数组名代表数组的首地址数组名代表数组的首地址:因此因此.a代表二维数组的首址代表二维数组的首址,(即第即第0行的首址行的首址),a+1:代表第一行的首址代表第一行的首址同理同理:a0为另一个一维数组的首址为另一个一维数组的首址(即第即第0行第行第0列元素的首址列元素的首址)即即:a0是是&a00;a0+1是是&a01;a0+2是是&a02a1为另一个一维数组的首址为另一个一维数组的首址(即第即第1行第行第0列元素的首址列元素的首址)即即:a1是是&a10;a1+1是是&a11;a1+2是是&a12即即:aij元元素素的的地地址址用用数数组组名名表表示示:aij或或*(a+i)+j与
16、与二维数组地址二维数组地址&aij一样一样aij元素值用数组名表示元素值用数组名表示:有以下几种等价形式有以下几种等价形式:*(ai+j)*(*(a+i)+j)(*(a+i)j/*数组名与下标混合表示数组名与下标混合表示*/或或:*(&a00+2*i+j)/*注注:inta23*/例例:编程用指针变量输出数组元素的值编程用指针变量输出数组元素的值.main()inta34=1,2,3,4,5,6,7,8,9,10,11,12;int*p;for(=a0;pa0+12;p+)if(p-a0)%4=0)printf(“n”);/*一一行行输输出出4个个数据数据*/printf(“%5d”,*p)3
17、)指向数组指针变量的定义指向数组指针变量的定义如如:int(*pa)3,a23;/*指指针针变变量量pa指指向向3个个元元素素的的数数组组*/pa=a;/*使使pa指向数组指向数组a的第的第0行行;*/注注:int(*pa)3与与int*pa3不不同同,后后者者为为由由三三个个指指针针组组成的指针数组成的指针数组.例例:上例上例:main()inta34=1,2,3,4,5,6,7,8,9,10,11,12;int(*p)4,j;for(p=a;pa+3;p+)for(j=0;j4;j+)printf(“%5d”,*(*p+j);printf(“n”);2.多维数组的指针表示多维数组的指针表示
18、三三维维及及以以上上的的数数组组用用指指针针表表示示比比较较复复杂杂,一一般般采采用用下下标表示元素法比较好;标表示元素法比较好;3.指向二维数组的指针变量的使用指向二维数组的指针变量的使用1)指针变量指向二维数组的某个元素指针变量指向二维数组的某个元素定义时:*指针变量指针变量=&数组名数组名下标下标1下标下标2引用时:指针变量指针变量=&数组名数组名下标下标1下标下标2例例:输入输入2行行3列的矩阵中的元素列的矩阵中的元素,存入二维数组存入二维数组,再按行再按行列输出列输出.main()inta23,*p;inti,j;for(i=0;i2;i+)for(j=0;j3;j+)p=&aij;
19、scanf(“%d”,p);inta23,*p=a;(或或*p=&a00).for(i=0;i2;i+)for(j=0;j3;j+)scanf(“%d”,p);p+;for(i=0;i2;i+)printf(“”)for(j=0;j3;j+)p=&aij;printf(“%5d”,*p);2)指针变量指向二维数组的首地址指针变量指向二维数组的首地址定义时:*指针变量指针变量=二维数组名二维数组名*指针变量指针变量=&三数组名三数组名00引用时:指针变量指针变量=二维数组名二维数组名指针变量指针变量=&二数组名二数组名003)指针变量指向二维数组中的某一个一维数组指针变量指向二维数组中的某一个一
20、维数组P=a;(或或p=&a00;)for(i=0;i2;i+)printf(“”)for(j=0;j3;j+)printf(“%5d”,*p);p+;24定义时:(*指针变量)m=二维数组名(m为列长)引用时:指针变量指针变量=二维数组名二维数组名数组元素的地址引用:*(指针变量+行下标)+列下标数组元素的内容引用:*(*(指针变量+行下标)+列下标)例:上例:main()inta23,(*p)3=a;inti,j;for(I=0;i2;i+)for(j=0;j3;j+)scanf(“%d”,*(p+i)+j);或或:*(a+i)+j;for(i=0;i2;i+)printf(“”)for(
21、j=0;j=1&nechohelloworld/*操作系统下的命令行操作系统下的命令行*/发布命令行的时刻发布命令行的时刻:在操作系统下执行时在操作系统下执行时如何将命令的参数接收到程序中如何将命令的参数接收到程序中?方法是方法是:通过函数通过函数main(argc,argv)中中argc,argv传送给传送给程序程序.其中其中:argc:计算命令行中参数的个数计算命令行中参数的个数argv:指针数组指针数组:每个元素是指向包含这些参数每个元素是指向包含这些参数(字字 符串符串)的指针的指针如如:cechohelloworldargc=3argv0=“echo”argv1=“hello”arg
22、v2=“world”参数参数argc,argv的定义的定义:main(argc,argv)intargc;char*argv;/*或或char*argv;).注注:1.argc和和argv位置不能颠倒位置不能颠倒2.argc和和argv的初始化的初始化,由键入的命令由键入的命令(包括命令字包括命令字)的的个个 数决定数决定.例例:编一命令行执行程序编一命令行执行程序:cechowhatdayistoday?输出命令行参数输出命令行参数:whatdayistaday?main(argc,argv)intargc;char*argv;while(-argc0)printf(“%s%c”,*+arg
23、v,(argc1)?:n);编译编译echo.c生成生成echo.exe文件文件,在在dos状态下执行状态下执行cechowhatdayistoday?显示显示:whatdayistoday?它告诉我们它告诉我们:可在操作系统状态下可在操作系统状态下,利用程序利用程序,接收字符接收字符串串,然后处理这些串然后处理这些串.例例如如:输输入入:cday22001/*设设计计程程序序day.c,接接收收月月份份,年份年份,显示该月的天数显示该月的天数*/四四:指向指针的指针变量指向指针的指针变量定义形式定义形式:类型标识符类型标识符*标识符标识符 例例:char*p;相当于相当于*(*p)其其中中:
24、*p是是指指针针变变量量的的说说明明,它它说说明明了了一一个个指指向向字字符符型型数数据的指针变量据的指针变量前前*()星号表示指针变量星号表示指针变量p是指向一个字符型指针是指向一个字符型指针 变量的指针变量变量的指针变量(指针变量的嵌套定义指针变量的嵌套定义)注注:访问内容时访问内容时,需要二次间址操作需要二次间址操作:用用*p表示表示:*p是是间间 接指向对象的地址接指向对象的地址,而而*p是是p间接指向的对象的值间接指向的对象的值.例例:#includemaininti,a5,*num5,*p;printf(“inputinteger5:n“);for(i=0;i5;I+)numi=&
25、ai;scanf(“%d”,numi);p=num;for(i=0;i5;i+)printf(“%5d”,*(*(p+i);输入:输入:integer5:输出:输出:.指针与函数指针与函数一一.指针变量作为函数参数指针变量作为函数参数 1.1.指针变量作为函数形参可改变对应实参的值指针变量作为函数形参可改变对应实参的值(传地传地址址)如如:main()inta=5;i=3,out;out=changer(&i)*i;printf(“%d%dn”,i,out);changer(int*index)intre;*index=7;re=5*(*index);return(re);注注:除数组名外除数
26、组名外,任何以任何以地址传递的实参变地址传递的实参变量必须在变量名前量必须在变量名前加上加上&符号符号,表示传表示传地址地址,在被调用函数在被调用函数中形参要说明为指针中形参要说明为指针2.通过指针参数可以从被调用参数中返回多个值通过指针参数可以从被调用参数中返回多个值例例.求求10个整数中奇数和偶数的个数个整数中奇数和偶数的个数voidcount(intx,intp1,intp2)if(x%2!=0)+*p1;else+*p2;main()inti,j,sum1=0,sum2=0;for(i=0;i=10;+i)scanf(“%d”,&j);count(j,&sum1,&sum2);prin
27、tf(“even=%d,odd=%dn“,sum2,sum1);2.指针作形参指针作形参,对应实参的形式对应实参的形式1)voidsort(int*v,intn)/*v和和*v都都是是数数组组指指针针变变量量*/2).调用函数调用函数inta10,*p;p=&a0;sort(p,10);.调用形式调用形式实现实现sort(a,5)a0,a1,a2,a3,a4排序排序sort(a+3,8)a3a1排序排序sort(&a4,10)a4a9排序排序2)形参说明为指向数组元素的指针形参说明为指向数组元素的指针,实参为数组元素的实参为数组元素的地址或指向元素的指针变量地址或指向元素的指针变量.如如:vo
28、idf(int*p,intsize).调用函数调用函数inta23;.f(a0,2*3);/*或或&a00*/.3)形参说明为指向下一级数组的指针形参说明为指向下一级数组的指针,实参为下一组数实参为下一组数组的指针组的指针,或指向下一级数组的指针变量或指向下一级数组的指针变量.如如:voidf(int(*pa)3,intsize).调用函数调用函数:inta23;f(a,2);或或inta23,(*p)3;p=a;f(p,2);C语言中语言中:函数不能返回数组函数不能返回数组,函数函数,结构结构,联合类型的联合类型的值值,但可以用返回指向此类数据的指针的方法实现但可以用返回指向此类数据的指针的
29、方法实现.二二.指向函数的指针变量指向函数的指针变量(函数指针函数指针)定义形式定义形式:类型标识符类型标识符(*指针变量名指针变量名)();例例:int(*p)();/*与与数数组组指指针针定定义义类类似似:char(*p)*/说说明明:1.p是是指指向向一一个个函函数数的的指指针针变变量量,(指指向向该该函函数数名名代代表的入口地址送指针表的入口地址送指针p),此函数返回此函数返回int类型的值类型的值2.用函数指针变量调用函数时用函数指针变量调用函数时,用函数名送入用函数名送入p中中即可即可.作用作用:利用函数指针将函数名传给一个函数利用函数指针将函数名传给一个函数.例例:求求a,b中的
30、最小数的程序中的最小数的程序.1.一般函数调用一般函数调用main()inta,b,c;scanf(“%d%d”,&a,&b);c=min(a,b);printf(“min=%dn”,c);min(intx,inty)intz;if(xy)z=x;elsez=y;return(z);min(intx,inty)intz;if(xy)z=x;elsez=y;return(z);mean(intx,inty)/*转右边转右边*/intz;z=(x+y)/2;return(z);main()inta,b,c,e,d;scanf(“%d%d”,&a,&b);p=max;c=(*p)(a,b);p=mi
31、n;e=(*p)(a,b);p=mean;d=(*p)(a,b);printf(“%d,%d,%dn”,c,e,d);通通过过函函数数指指针针将将函函数数名名作作为为参参数数传传给给其其他他函函数数,便便能能创创造造出出功功能能很很强强的的高高级级函函数数系系统统,在在大大型型c程程序序设设计计中中很很有有作作用用定义另一个函数定义另一个函数all如下如下voidall(intx,inty,func)int(*func)();/*函数名传递函数名传递*/intz;z=(*func)(x,y);printf(“%dn”,z);main()inta,b;scanf(“%d%d”,&a,&b);al
32、l(a,b,max);all(a,b,min);all(a,b,mean);三三.指针函数指针函数(与指针数组类似与指针数组类似)返回指针的函数返回指针的函数定义形式定义形式:类型标识符类型标识符*函数名函数名(参数表参数表);例例:int*f(x,y);/*与指针数组类似与指针数组类似:int*f10;*/返回值是一个指向整型数据的指针返回值是一个指向整型数据的指针.(可返回数组的首址可返回数组的首址,结构首址结构首址,联合首址联合首址,指针变量的地址和变量地址指针变量的地址和变量地址)例,将两个字符串连成一个串,并输出。例,将两个字符串连成一个串,并输出。char*cat(char*p1,
33、char*p2)staticchara160,*p;p=a;while(*p1!=0)*p+=*p1+;while(*p2!=0)*p+=*p2+;*p=*p2;return(a);main()chars180,s280;scanf(“%s”,s1);scanf(“%s”,s2);printf(“%sn”,cat(s1,s2);上机题上机题(以下各题全部用指针方法实现和数组方法完成以下各题全部用指针方法实现和数组方法完成)1.编编程程:输输入入15个个整整数数存存入入一一维维数数组组,再再按按逆逆序序重重新新存存放放入入再输出再输出2.编编程程:输输入入一一个个字字符符串串,按按相相反反次次序
34、序输输出出其其中中的的所所有有字字符符3.编编程程:输输入入10个个整整数数,将将其其中中最最大大数数和和最最后后一一个个数数交交换换,最最小数和第一个数交换小数和第一个数交换,然后显示这然后显示这10个数个数4.编编程程:输输入入三三个个字字符符串串.输输出出其其中中最最长长的的字字符符串串,(要要求求:将将求串长编写成函数然后调用求串长编写成函数然后调用)练习题练习题1.将下列函数的数组参数将下列函数的数组参数,改写成指针参数改写成指针参数,且使函数的且使函数的2.功能不变功能不变floatav(a,n)floata;intn;inti;floats;for(i=0,s=0;in;i+)s
35、=s+ai;return(s/n);1.阅读下列程序写出运算结果阅读下列程序写出运算结果1)unsignedf(unsignednum)unsignedk=1;dok*=num%10;num/=10;while(num);return(k);main()unsignedn=26;printf(“%dn”,f(n);2)chars=”ABCD”;main()char*p;for(p=s;ps+4;p+)printf(“%s”n”,p);3.编编程程:输输入入个个整整数数存存入入一一维维数数组组中中,统统计计其其中中既既能能被被整整除除又又能能被被整整除除的的数数的的个个数数(用用组组数数和和指指针针两两种种方式做)同时显示这些数在该数组中的下标值方式做)同时显示这些数在该数组中的下标值4.编程:输入一个字符串,间隔显示其中的字符(用编程:输入一个字符串,间隔显示其中的字符(用指针和数组两种方法做)如:指针和数组两种方法做)如:显示显示:回答下列各题回答下列各题1)x是指向是指向25的指针,的指针,printf(“%dn”,+*x);输出什么值输出什么值2)inta10=1,2,3,4,5,6,7,8,9,10;p=a;则则p+=3;+*p;执行后执行后p指示的对象的值是多少指示的对象的值是多少3)执行执行chara10=“abcd”;*p=a后后,*(p+4)的值是多少的值是多少
限制150内