1、单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,华中科技大学计算机学院,C,语言程序设计,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,第08章 指针,本章主要,指针的概念、运算、使用、各种类型的指针、指针数组、类型表达式与复杂类型声明,还讨论了与动态存储分配的相关操作。,内容摘要,2,重点讲解,8.1,指针的概念与指针的使用,8.2,指针运算,8.3,指针作为函数的参数,8.4,数组的指针表示,8.5,指针数组,8.6,带
2、参数的,main,函数,8.7,指针函数,8.8,函数的指针,8.9,指向数组的指针,(见教材第,11,章),8.10,用,typedef,定义类型表达式,8.11,复杂说明的解释,8.12,复杂说明的应用,小结,3,8.1.1,指针概念,目录,8.1,指针的概念与指针的使用,在计算机高级语言中,存储数据的内存单元称为变量,并使用变量名引用之。变量的占用内存的大小和存储数据的格式,是由数据类型确定的。,内存单元之地址称为指针,存储指针的内存单元称为指针变量。,int x;float y;char z;,x,y,z,&x,&y,&z,int x;,x,p,&x,指针变量如何声明?,?,?,int
3、型地址,float,型地址,char,型地址,4,在指针变量说明语句的一般形式如下:,数据类型*标识符,1,=,初值,1,*,标识符,2,=,初值,2,*,标识符,n,=,初值,n,;,其中,*为指针类型符;数据类型为指针所指存储单元之类型,亦称为指针类型,标识符,i,为指针变量名;初值,i,为指针类型表达式。,int *float *char*,8.1.2,指针的声明,C,语言提供指针数据类型,*为指针类型符,用于声明存储指针的内存单元即指针变量。,int,float,char,int x;,x,p,&x,int *p=,int,型地址,float,型地址,char,型地址,5,根据指向变
4、量之数据类型,指针类型可划分为不同数据类型。,char,*,int*,float*,double*,long double*,signed char*,unsigned char*,signed int*,unsigned int,*,signed long int*,signed short int*,signed int*,unsigned long int*,unsigned short int*,unsigned int*,整型类型指针,浮点类型指针,字符类型指针,void*,6,例,8.3,解释以下复杂声明的含义。,(,1,),int,(*,p1,),3,;,p1,是指向,3,个元素
5、的整型数组的指针。,(,2,),double,*,p25,;,p2,是指针数组。,(,3,),char,(*,fp,),(int,int),fp,是一个函数指针,所指向的函数有,2,个整型形参,返回类型,char,。,(,4,),int,*,pf,(,float,),pf,是指针函数。,(,5,),int,(*,fp_ary2,),(char *,char*),fp_ary,是一个函数指针数组,该数组的每一个下标变量都是函数指针。,7,8.1.3,指针的使用,C,语言提供单目运算*为指针指向的内存单元即变量之引用,提供表达方式。,单目*运算的一般形式是:,*右操作数,其中,右操作数为指针表达式
6、运算结果为右操作数指针所指内存单元即变量之名称。,int x;,x,p,&x,int *p=,*P,变量,x,之,“,别名,”,x=1;x=x+1;x+;,*p=1;*p=*p+1;(*p)+;,8,大家学习辛苦了,还是要坚持,继续保持安静,9,int x,*p=,8.2,指针运算,目录,8.2.1,指针的算术运算,指针类型的算术运算限于加法和和减法,因为其它算术运算无意义。,指针运算的一般形式是:,表达式,1,表达式,2,或,表达式,1,-,表达式,3,其中,表达式,1,为指针表达式;表达式,2,为整整表达式,(,0,),;表达式,3,为整型或指针表达式,(,0,),;,式为指针类型,值为
7、表达式,1,表达式,2,sizeof(,表达式,1,),;,式为整型类型,值为,(,表达式,1,-,表达式,3,),sizeof(,表达式,1,),。,x,p,&x,*p,p,-1,值:,p,+1,值:,*(p-1),*(p+1),(p+1)-(p-1),值:,2,10,8.2.2,指针的赋值运算和关系运算,指针赋值的一般形式是:,表达式,1,表达式,2,其中,表达式,1,为左值表达式;表达式,2,为指针表达式,运算结果值和类型与表达式,1,一致,。,int a8=1,2,3,4,5,6,7,8,*p=,p,a,q,q=p+3,*p,*q,指针类型可以进行,、,、,=,、,=,和,!=,关系运
8、算,运算结果为逻辑类型。,11,不同基本类型指针之间的赋值运算,必须使用类型强制。利用指针的赋值运算以及类型强制可以实现一些特殊操作。,#include stdio.h,void main(void),long x=0 x1234ABCD,k;,char*p=,(char*),/*,类型强制,,p,为字符指针*,/,char up_half,low_half;/*up_half,存高,4,位,,low_half,存低,4,位*,/,for(k=0;k4;k+),low_half=(*p)/*,取低,4,位*,/,if(low_half4)/*,取高,4,位*,/,if(up_half10)up
9、half|=0;/*,高,4,位转换成,ASCII,码,0-9*/,else up_half=(up_half-10)+A;/*,高,4,位转换成,ASCII,码,A-F*/,p+;/*,指向整型数,x,下一个字节*,/,printf(%c%c,up_half,low_half);,例,8.1,1,试从占,4,个字节的长整型数之低字节开始,依次取出其每个字节的高,4,位和低,4,位并以,ASCII,码的形式进行显示。,C D A B 3 4 1 2 _,12,8.3,指针作为函数的参数,目录,指针作为函数的参数是指数据类型为指针的函数参数,称为指针参数。指针参数作用是实现子程序之间数据的双向
10、交换。,8.3.1,形参指针对实参的影响,例,8.12,被调用函数中对形参的修改无法影响调用函数中实参变量的值举例。,#include stdio.h,void s u,int v);,void main(void),int x,y;,printf(input two integers for x and y please!n);,scanf(%d%d,printf(in function main,before s and y=%dn,x,y);,s);,printf(in function main,after s and y=%dn,x,y);,void s u,int v),int t
11、printf(in function swap,before s and v=%dn,u,v);,t=u;u=v;v=t;,printf(in function swap,after s and v=%dn,u,v);,13,main,#include stdio.h,void s u,int v);,void main(void),int x,y;,printf(input two integers for x and y please!n);,scanf(%d%d,printf(in function main,before s and y=%dn,x,y);,swap(,x,y,);
12、printf(in function main,after s and y=%dn,x,y);,void swap(,int u,int,v,),int t;,printf(in function swap,before s and v=%dn,u,v);,t=,u,;,u,=,v,;,v,=t;,printf(in function swap,after s and v=%dn,u,v);,x,y,swap,u,v,t,10 20,10,20,x=10 and y=20,10,20,u=10 and v=20,20,10,10,u=20 and v=20,x=10 and y=20,14,
13、main,#include stdio.h,void s*u,int*v);,void main(void),int x,y;,printf(input two integers for x and y please!n);,scanf(%d%d,printf(in function main,before s and y=%dn,x,y);,swap(&,x,&,y,);,printf(in function main,after s and y=%dn,x,y);,void swap(,int*u,int*v,),int t;,printf(in function swap,before
14、s,p,and v=%,p,n,u,v);,t=,*u,;,*u,=,*v,;,*v,=t;,printf(in function swap,after s,p,and v=%d,p,u,v);,x,y,swap,u,v,t,10,20,10 20,x=10 and y=20,u=,and v=,20,10,10,u=,and v=,x=20 and y=10,15,8.3.2,指针作为参数的应用,例,8.14,将键盘输入的所有数字串逐个的转换为整数,并且依次存放于一个数组中。数字串前面可以加,+,、,-,号,各数字串之间至少用一个空格分开,用回车结束输入。,#include stdio.h,
15、include ctype.h,#define NUMBER 100,int getint(int*pn),int c,sign;,while(isspace(c=getchar();,/*,跳过前导空格*,/,if(!isdigit(c),/*,若输入为非数字、非,EOF,、也不是,+,、,-,号,显示出错*,/,sign=(c=-)?-1:1;,/*,处理符号*,/,if(c=+|c=-)c=getchar();,/*,跳过,+,、,-,号*,/,for(*pn=0;isdigit(c);c=getchar(),*pn=10*pn+(c-0);,/*,将数字串转换为对应整数*,/,*pn
16、sign;,/*,处理整数的符号*,/,return c;,void main(void),int aNUMBER,i,j,k;,printf(input integers ends with Entern);,for(i=0;i NUMBER),if(k)i+;,for(j=0;j=i;j+),printf(%8d,aj);,printf(n);,16,8.4,数组的指针表示,8.4.1,一维数组的指针表示,目录,int a6,*p=a;/*,或,=&a0*/,a,p,*(+p)=0;,0,数组名是常量地址,其类型是数组元素类型指针。,17,pc=s,对字符指针变量,pc,赋值,使其指向
17、字符数组,s(,即,s0),pc+i,结果为,pc,后面第,i,个元素的地址,*,(pc+i),结果为,pc,后面第,i,个元素,*,+pc,结果为,pc,加,1,之后所指元素,+*pc,结果为,pc,所指元素加,1,*pc+,结果为,pc,所指元素,然后,pc,加,1,(*pc)+,结果为,pc,所指元素,然后,pc,所指元素加,1,&pc,结果为字符指针变量,pc,的地址,类型为,char*,char s6=0,1,2,3,4,5,*pc ;int i=2;,s,pc,运算符表,2,3,特别提示:注意运算符的优先级和结合性!,18,char s6=0,1,2,3,4,5,*pc=,s,pc
18、运算符表,s+i,结果为数组,s,中第,i,个元素的地址,(,即,si,的地址,),*(s+i),结果为数组,s,中第,i,个元素,si,+*s,结果为元素,s0,加,1,(*s)+,结果为元素,s0,的值,然后,s0,加,1,特别提示:注意运算符的优先级和结合性!,1,2,s=pc,非法。数组名,s,是地址常量,不能进行赋值操作,&s,非法。数组名,s,是地址常量,不能取地址,*,+s,非法。不能对数组名,s,进行前缀,+,操作,*,s+,非法。不能对数组名,s,进行后缀,+,操作,?,&s,类型为,char(*)6,19,8.4.2,一维数组参数的指针表示,对于函数形如,int f(in
19、t a,,,),的形参,a,,其类型,int,实质上是整型指针,即:,int*,。,S1=15,int fun(int x,int n),int i,sum=0;,for(i=0;in;i+),s+=xi;,return(s);,void main(void),int y=1,2,3,4,5;,printf(”s1=%dn”,fun(y,5);,printf(,”,s2=%dn,”,fun(,main,:,y,fun,:,x,int,型地址单元,S2=12,int*x,20,例,8.15,用指针变量表示一维数组参数,计算两个向量的数量积。,#include stdio.h,#define SI
20、ZE 3,double scalar(double*a,double*b,int n);,void main(void),double xSIZE,ySIZE,*px,*py;,for(px=x;pxx+SIZE;px+)scanf(%lf,px);,getchar();,for(py=y;py,px=x;py=y;,printf(the scalar of vector x and vector y is%lfn,scalar(px,py,SIZE);,printf();,double scalar(double*a,double*b,int n),double s,*p;,printf(t
21、he vector a isn);,for(p=a;pa+n;)printf(%lft,*p+);,printf(nthe vector b isn);,for(p=b;pb+n;)printf(%lft,*p+);,printf(n);,for(s=0,p=a;pa+n;),s+=(*p+)*(*b+);,return s;,21,8.4.3,用指向数组基本元素的指针表示多维数组,int a,4,2,*p=a 0;/*,或,=&a00*/,a,p,*(p+0*2+0),*(p+0*2+1),*(p+1*2+0),*(p+1*2+1),*(p+2*2+0),*(p+2*2+1),*(p+3*2
22、0),*(p+3*2+1),int a,M,N,*p=a0;/*,或,=&a00*/,a,p,p+i*N+j,在,aij,之前,int,单元个数,*(p+i*N+j),a0,a1,a2,a3,什么类型的指针?,?,上机操作演示,9-4-3.c,22,例,8.16,用指向数组基本元素的指针变量实现三维数组元素的输入和输出。,#include stdio.h,#define,I,2,#define,J,3,#define,K,4,void main(void),int vIJK,*p=&v000,n=1,i,j,k;,for(i=0;iI;i+),for(j=0;jJ;j+),for(k=0;k
23、K;k+),*(p+i*J*K+j*K+k),=n+;,for(i=0;iI;i+),for(j=0;jJ;j+),for(k=0;kK;k+)printf(%4d,*(vij+k),);,printf(n);,printf(n);,23,8.5,指针数组,8.5.1,指针数组的声明及使用,数组元素为指针类型的数组,称为,指针数组,。,目录,int*p3;,p,是有,3,个元素的整型指针数组,(,int*3,),。说明的顺序是:,p,3,*,int,p,char*pstr=”123”,”5678”;,pstr,是有,2,个元素的字符指针数组,(,char*2,),。,pstr,24,const
24、 int x=1,y=2;,const int*ps2;,ps0=,x,y,ps,x,和,y,变量是常量整型,(,const int,),,即,x,和,y,是,必须赋初值、且不得改变的变量,也称为,符号常量,。,ps,是有,2,个数组元素的常量整型指针数组,(,const,int*2,),。,char*const pstr=”123”,”5678”;,pstr,值不得改变!,const,char*const pstr=”123”,”5678”;,pstr,值不得改变!,25,例,8.18,理解指针数组含义的编程举例。,#include stdio.h,void main(void),int x
25、1,y=2,z=3,i;,int*p3;,p0=,printf(,printf(,printf(,for(i=0;i3;i+),printf(,printf(p%d=%pt“,i,pi);,printf(*p%d=%dn,i,*pi);,p,z,y,x,&x=FFD0 x=1,&y=FFD2 y=2,&z=FFD4 z=3,&p0=FFD6 p0=FFD0 *p0=1,&p1=FFD8 p1=FFD2 *p1=2,&p2=FFDA p2=FFD4 *p2=3,26,对指针数组中元素可以进行同类型指针允许的全部操作。,int a=1,2,3,b=4,5,6,*p2;,p0=a;,/*,对指针数
26、组中的元素,p0,赋值,使之指向,a,数组*,/,p1=b;,/*,对指针数组中的元素,p1,赋值,使之指向,b,数组*,/,*p0=12;,/*,使,a0=12*/,+*p1;,/*,间访,b0,并使其自增,结果为,5,,,p1,仍然指向,b0*/,*p1+;,/*,间访,b0,,然后,p1,自增,使,p1,指向,b1*/,a,p,b,12,5,运算符表,27,例,8.19,未赋值指针数组引起的副作用举例。,#include stdio.h,#define N 6,void main(void),int i,*pN,sum=0;,for(i=0;iN;i+),scanf(%d,pi);,su
27、m+=*pi;,for(i=0;iN;i+),printf(p%d=%p,result=%dn,i,pi,*pi);,printf(sum=%dn,sum);,p,1 2 3 4 5 6,p0=0000,result=4,p1=FFDC,result=2,p2=0580,result=3,p3=0000,result=4,p4=0040,result=5,p5=0C39,result=6,sum=21,Null pointer assignment,28,例,8.2,0,解决未赋值指针数组引起的副作用举例。,#include stdio.h,#define N 6,void main(void
28、),int i,aN,*pN,sum=0;,for(i=0;iN;i+),pi=,scanf(%d,pi);,sum+=*pi;,for(i=0;iN;i+),printf(p%d=%p,result=%dn,i,pi,*pi);,printf(sum=%dn,sum);,p,a,1 2 3 4 5 6,p0=FFCA,result=1,p1=FFCC,result=2,p2=FFCE,result=3,p3=FFD0,result=4,p4=FFD2,result=5,p5=FFD4,result=6,sum=21,1,2,3,4,5,6,29,#include stdio.h,void m
29、ain(void),int x05,x15,x25,x35,x45;,int*p5;,int i,j;,p0=x0;p1=x1;,p2=x2,p3=x3,p4=x4;,for(i=0;i5;i+),for(j=0;j5;j+),if(i=j)pij=1;,else pij=0;,for(i=0;i5;i+),for(j=0;jcopy abc.txt def.txt,在,DOS,下执行,copy,命令,将一个文件,abc.txt,的内容拷贝到另外一个文件,def.txt,。,C,语言编制的可执行程序,对于命令行提供的实际参数,将由,C,程序之,main,函数定义的形式参数接受。即对于,C,语言
30、命令行参数就是,main,函数的参数。,在,DOS,下,命令行一般格式如下,文件名和参数以及参数和参数之间是空格符间隔。,可执行文件名 参数,1,参数,2,参数,n,32,8.6.2,带参,main,函数的声明及使用,声明具有命令行参数的,main,函数的一般形式是:,类型,main(int argc,char*argv),/,函数体,其中,类型为,main,的函数类型;,argc,值表示命令行中字符串的个数,;,argv,的每个字符指针元素指向一个命令行中的字符串。,c:,程序名 参数,1,参数,2,参数,n,argc,argv,程序名,0,参数,1,0,参数,2,0,参数,n,0,33,
31、include stdio.h,int main(int argc,char*argv),int n=0;,while(nargc),printf(,“,%s,”,argvn);,(nshow I like C programming.,C:show I like C programming.,C:the number of command-line arguments are 5,34,例,8.2,7,用其它自定义名字表示,main,函数命令行形参的例子。,#include stdio.h,int main(int,num,char*,v,),int n=0;,while(nnum),pr
32、intf(,printf(,printf(v%d=%sn,n,vn);,n+;,return 0;,程序中分别用整型形参,num,和形参字符指针数组,v,来表示,main,函数的命令行参数。,35,定义指针函数的一般形式是:,类型,*函数名,(,形参表,),/,函数体,;,其中,函数名之函数类型为,类型,*,;类型为任意数据类型。,声明指针函数的一般形式是:,类型,*函数名,(,形参表,),;,其中,函数名之函数类型为,类型,*,;类型为任意数据类型。,8.7,指针函数,8.7.1,指针函数的声明与定义,一个函数返回值为指针类型之函数,称为指针函数。,目录,除了返回类型之外,指针函数与其它类型
33、函数之特性一样。,char*strcpy(char*t,char*s),char*p=t;,while(*s+=*t+);,return p;,36,#include stdio.h,char*strstr(char*s,char*t),char*ps=s,*pt,*pc;,while(*ps!=0),for(pt=t,pc=ps;*pt!=0,if(*pt=0)return ps;,ps+;,return 0;,void main(void),char s1=abcdefghijk12,s2=fgh,*p;,p=strstr(s1,s2);,printf(%pt%sn,printf(%pt%
34、sn,p,p);,8.7.2,指针函数的使用,例,8.28,查找子串的指针函数应用举例。,s1,s2,s,t,ps,pt,p,FFCC abcdefghijk,FFD1 fghijk12,pc,37,声明函数指针的一般形式是:,类型,(,*,函数指针名,)(,形参表,),;,其中,函数指针名是指针变量名,所指函数的类型为,类型,(,形参表,),;类型为指向的函数类型;参数表是指向的函数形参表。,8.8,函数的指针,8.8.1,函数指针的声明,如果一个指针存放的是函数的入口地址,则该指针称为函数指针。,函数指针变量,函数,所指函数的类型和参数,必须与指针对象类型即,类型,(,形参表,),一致!,
35、目录,38,函数指针赋值的一般形式是:,函数指针名,函数名,;,其中,函数名是已经定义的函数之名称,其类型应与函数指针名所指函数类型即,类型,(,形参表,),一致。,通过函数指针调用所指函数的一般形式是:,(,*,函数指针名,)(,实参表,),或,函数指针名,(,实参表,),其中,实参表的参数个数与类型,应与函数指针名所指函数的形参表一致。,函数名是地址常量,其值为函数之入口地址。,39,例,8.29,函数指针的应用举例。,#include stdio.h,void f1(int x),printf(function f1 is called!n);,printf(x=%dn,x);,void
36、 f2(int x,int y),printf(function f2 is called!n);,printf(x=%dty=%dn,x,y);,void main(void),void(*pf1)(int x);,void(*pf2)(int x,int y);,pf1=f1;pf2=f2;,pf1(5);,pf2(10,20);,(*pf1)(50);,(*pf2)(100,200);,pf1,pf2,function f1 is called!,x=5,function f2 is called!,x=10 y=20,function f1 is called!,x=50,functi
37、on f2 is called!,x=100 y=200,40,8.8.2,函数指针的应用,例,8.3,0,读取从键盘输入正文,再将正文以行为单位排序后输出。通过命令行参数,-n,决定排序方法。如果有命令行参数,-n,,则将输入行按照数值大小进行排序;否则将按照字典顺序排序。,main,readlines,writelines,sort,numcmp,strcmp,getline,swap,void sort(void*v,int n,int(*comp)(void*,void*),int i,j;,void s*v,int,int);,for(i=0;in-1;i+),for(j=0;j0)
38、s);,41,8.9,指向数组的指针(教材第,11,章内容),8.9.1,指向数组指针的声明与定义,一个,指针类型为数组的指针,称为数组指针。,目录,声明指针函数的一般形式是:,类型,(,*,指针名,),M,1,M,2,M,n,;,其中,指针名指向的数组之类型为,类型,M,1,M,2,M,n,。,int u23,*p=&u00,(*p1)3=u,;,u,p,p1,p,数据类型为,int*,,其指向的存储单元之数据类型为,int,。,p1,数据类型为,int(*)3,,其指向的存储单元之数据类型为,int3,。,数组名是常量地址,其类型是数组元素类型指针。,u,地址类型为:,int(*)3,42
39、8.9.2,用数组名间访多维数组的元素,一,个,n,维数组是其数组元素为,n-1,维数组的一维数组。,int AM,1,M,2,M,3,M,n,;,数组,A,是类型为,M,1,一维数组,其元素是类型为,intM,2,M,3,M,n,的,n-1,维数组。,A,是一个指向其数组元素,n-1,维整型数组之常量指针,其值为,n,维数组之首地址。,*,A,是,A,所指向,n-1,维整型数组。,int,a32;,a,int(*)2,int*,int,43,假设,i,j,k,m,n,皆未使数组下标越界,用数组名,数组名和下标操作符等非左值常量指针表示多维数组的元素形式是:,对于二维整型数组,u,,其,ui
40、j,元的地址用指向数组元素的指针表示为:,ui+j,用指向一维数组(下一级数组)的指针表示则为:,*,(u+i)+j,用间访形式访问其,uij,元可以表示为:,*,(ui+j),和 *,(*(u+i)+j),int,a32;,a,a2+1,*(a+2)+1,*(a2+1),*(*(a+2)+1),44,一,个,n,维数组是其数组元素为,n-1,维数组的一维数组。,int AM,1,M,2,M,3,M,n,;,A,是一个类型为:,int,(*),M,2,M,3,M,n,;的数组的指针。,一般情况:一个,n,维数组的名字(或别名)是对应,n-1,维数组的指针。,*,(A+i),是一个,n-1,维数
41、组的别名,为对应,n-2,维数组的指针。类型为:,int,(*),M,3,M,n,;,等价形式为,Ai,*,(,*,(A+i)+j),是一个,n-2,维数组的别名,为对应,n-3,维数组的指针。类型为:,int,(*),M,4,M,n,;,等价形式为,Aij,可以理解,0,位数组的指针就是对应数据类型的指针(如,int,*),45,假设,i,j,k,m,n,皆未使数组下标越界,用数组名,数组名和下标操作符等非左值常量指针表示多维数组的元素形式是:,对于三维整型数组,v,,其,vijk,元的地址用指向数组元素的指针,vij,表示为:,vij+k,用指向一维数组的指针,vi,表示为:,*,(vi+
42、j)+k,用指向二维数组(下一级数组)的指针,v,表示为:,*,(*(v+i)+j)+k,用间访形式访问其,vijk,元可以表示为:,*,(vij+k),*(*(vi+j)+k),*(*(*(v+i)+j)+k),46,例,11.2,用数组名常量指针实现二维数组元素的输入和输出。,#include stdio.h,#define N 2,#define M 3,void main(void),int uNM;,int j;,/*,用指向数组元素的指针完成第,0,行元素的输入*,/,for(j=0;jM;j+)scanf(%d,u0+j,);,/*,用指向下一级数组的指针完成第,1,行元素的输入
43、/,for(j=0;jM;j+)scanf(%d,*(u+1)+j,);,/*,用指向下一级数组的指针完成第,0,行元素的输出*,/,for(j=0;jM;j+)printf(%6d,*(*(u+0)+j),);,printf(n);,/*,用指向数组元素的指针完成第,1,行元素的输出*,/,for(j=0;jM;j+),printf(%6d,*(u1+j),);,printf(n);,47,8.9.4,多维数组参数的指针表示,1.,形参为指向数组元素的指针,形参说明为指向数组元素的指针时,实参应为数组元素的地址,或为指向数组元素的指针变量。,void fun(,int*p,int n);
44、/*,形参说明为指向数组元素的指针*,/,void main(void),int u23,v234;,fun(,u0,2*3);/*,实参,u0,是元素,u00,的地址*,/,fun(,v00,2*3*4);/*,实参,v00,是元素,v000,的地址*,/,48,8.9.4,多维数组参数的指针表示,2.,形参为指向下一级数组的指针,形参说明为指向下一级数组的指针时,实参应为数组名或指向下一级数组的指针。,void f1(,int(*p1)3,int n);/*,指向一维数组的指针,p1,为形参*,/,void f2(,int(*p2)34,int n);/*,指向二维数组的指针,p2,为形参
45、/,void main(void),int u23,v234;,f1(,u,2*3);/*,数组名,u,作为实参*,/,f2(,v,2*3*4);/*,数组名,v,作为实参*,/,49,8.10,用,typedef,定义类型,8.10.1,类型表达式,C,中另外一类表达式是类型表达式。类型表达式是由类型说明符和数据类型名所组成的式子,表示一种数据类型。,目录,运算符表,可用于类型表达式的类型说明符有:,(),、,、*。,(),函数类型说明符、或改变优先级;,数组类型说明符;,*指针类型说明符。,表,9.2,类型说明符和数据类型名的优先级与结合性,50,8.10.2,用,typedef,定义
46、类型表达式,1.,在声明语句中出现的类型表达式,在声明语句中去掉对象标识符和语句分号后,剩余部分是一个类型表达式。,int*p3;,int*3,p,3,*,int,第步:,p,是一个有,3,个元素的数组;,第步:,p,是一个有,3,个元素的指针数组;,第步:,p,是一个有,3,个元素的,int,类型的指针数组。,p,51,8.10.2,用,typedef,定义类型表达式,2.,在,tyoedef,定义中出现的类型表达式,typedef,是,C,的一个关键字,使用它可以用一个标识符为一个类型表达式命名。,对于已有数据类型,用,typedef,定义类型的一般形式是:,typedef,数据类型名 标
47、识符表列,;,例如:,typedef unsigned int UINT,size_t;,对于复杂的类型表达式,标识符往往出现在类型表达式中间,暂且称这种含标识符和类型表达式的式子为类型定义表达式。,typedef,定义类型的一般形式是:,typedef,类型定义表达式,;,例如:,typedef char*(*p_to_fun)(char*,char*);,p_to_fun,是一个函数指针类型,其所指是一个有两个字符指针形参的字符指针函数。,52,8.11,复杂说明的解释,解释下面的声明语句:,char*(*(*f(char*(*)(int)2)();,根据优先级和结合性可以得到声明语句的解
48、释顺序如下:,f,(char*(*)(int),*,2,*,(),char*,第步,f,是一个函数;,f,函数的形参为一个函数指针,该函数指针所指函数有一个整型形参且返回值类型为,char*,。,第步,f,函数的返回值是一个指针。,第步,f,函数的返回值是一个指向有两个元素的数组的指针。,第步,f,函数的返回值是一个指向有两个元素的指针数组的指针。,第步,f,函数的返回值是一个指向有两个元素的函数指针数组的指针,数组中每个函数指针元素所指函数是无参函数。,第步,f,函数的返回值是一个指向有两个元素的函数指针数组的指针,指针数组中每个函数指针元素所指函数是无参函数且返回值的类型是,char*,。
49、目录,53,例,11.,7,有两个元素的函数指针数组的复杂说明的使用举例。,8.12,复杂说明的应用,目录,#include stdio.h,int a1(int),;,int a2(int),;,void main(void),int i;,int(*fpa2)(int),;,fpa0=a1;fpa1=a2,;,for(i=0;i2;i+)printf(%dn,fpai(i+1)*5);,int a1(int x),printf(in function a1,x=%dn,x);,return 2*x;,int a2(int y),printf(in function a2,y=%dn,y);,return 2*y;,54,本章介绍了指针的概念与指针的引用、指针运算、指针作为函数的参数,数组的指针表示、指针数组、指针悬空引起的副作用、带参数的,main,函数、函数指针、指针函数、指向数组的指针。,另外,讨论了字符指针与字符串,指针形式的字符串函数的实现,创建自己的字符串库,字符串的递归处理。,最后讨论了复杂说明,其属,C,语言中难度大的部分。,小结,目录,55,






