《华中科技大学光电子学院C语言第七章.ppt》由会员分享,可在线阅读,更多相关《华中科技大学光电子学院C语言第七章.ppt(48页珍藏版)》请在三一办公上搜索。
1、1,第七章 指 针 1.指针与数组的关系 2.指针与函数的关系,1.指针及定义 一.指针变量的定义 指针变量:存放对象地址的变量.指针变量定义的基本形式:类型说明符*变量名;例:int*pi,*pj;/*pi,pj指向整型变量的指针变量*/float*p3;/*p3是指向浮点型变量的指针变量*/注:1.定义指针变量的物理意义:机器给指针变量分配内存 单元,此单元只能存放对象的地址,2,2.指针类型是指针所指对象的类型(指针本身没有类型)例:int*fpi(),*a10,(*pa)10;/*复杂变量的指针*/fpi是一个整型指针函数(函数返回值是指向int变量的指针)a是含有10个元素的整型指针
2、数组(每个元素是一个指向int变量的指针)pa是指向含有10个int元素的数组的指针,3,二.指针变量的运算符,指针变量运算符,*:间接取对象的内容&:取操作对象的地址,(都是一目运算符),例:int*p,*p1,t,t1;p=/*将0送p指向的t单元中,即t=0*/,4,例:int i,j,*p;1)i=123;2)p=表达式:&r,&a0,&a1 是正确的,&(2*r),&a,&k 是非法的,5,2).*与/*直接寻址,访问c*/,6,三.指针运算 1.赋值运算 1).同类型的指针变量可以相互赋值,(指向同一类型的对 象)int*p1,*p2,a;p1=,7,4)两种特殊指针:void指针
3、和NULL指针 void指针:指向空值类型的指针变量:可以与任何类型 指针变量相互赋值(不需要强制类型转换)如:int*p;void*p1;p=p1;p1=p;NULL指针:具有整数0值的指针:即不指向任何对 象的指针 NULL符号常量:在有定义:或用#define NULL 0 定义,void*f();/*f是无参数的指针函数*/void*pa=,8,例:main()int*p1,*p2,*p,a,b;scanf(“%d%d”,9,2.算术运算 仅限于加法和减法 1)指针变量加(减)一个整数.int*p,*p1;p+;/*访问p后,p从当前位置向后移一个单元的数据*/p-;/*访问p后,p从
4、当前位置向前移一个单元的数据*/-p;/*访问p前,p从当前位置向前移一个单元的数据*/p+5;/*指向p当前所指数据后面第5个单元的数据.,2).同类型指针变量之间仅只能相减,结果为整数,(不为指 针,大小为相隔的字节数)如:上面 p-p1;注:不允许两指针变量相加,乘除,移位,屏敝运算,以及float 或double数与指针相加运算,10,例:用指针定义求字符串长度的函数int strlen(char*s)char*p=s;while(*p!=0)p+;return(p-s);,3.关系运算 两个指针指的类型相同,可以进行比较(,=,q 若值为非0,则p所指的数据位于q所指的数据 之前,反
5、之为0 指针变量不能与常量比较,但常量0(NULL)可与任何类 型的指针变量作=或!=的比较,11,2.指针与数组 指针与数组有密切关系:任何由数组下标完成的操作,都可由指针实现.一一维数组的指针表示 例:int a10,*pa;pa=(或 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 的内容,12,注:1)当指针变量指向数组首址后,以下标为i的数组元素引用 的方法有3种*(指针变量+i),*(数组名+i),数组名i 指针法 数组元素法,2)
6、数组名与指针之间有区别:指针是变量;数组名是地址常量 如:pa=a;pa+;是有意义的操作 a=pa;a+;pa=都是非法的.访问一个数组元素:可用下标法:ai,也可用指针法:*(p+i)或*(a+i),13,1).下标法:main()int i,min,max,a10;for(i=0;i max)max=ai;else if(ai min)min=ai;printf(“max=%d,min=%dn”,max,min);,例:求整型数组a10中的最大值和最小值,14,2)用数组名访问元素main()int i,min,max,a10;for(i=0;i max)max=*(a+i);else
7、if(*(a+i)min)min=*(a+i);printf(“max=%d,min=%dn”,max,min);,15,3)用指针间接访问 main()int*p,min,max,a10;p=a;for(;p max)max=*p;else if(*p min)min=*p;printf(“max=%d,min=%dn”,max,min);,16,注:1.指针变量的定义和没有指明长度的数组视为一样例:在函数定义中;参数说明:f(char s)f(char*s)2.在C语言中,只要出现未加下标的数组名,字符串常量名,结构名,联合名或不带参数的函数名,都可以解释成指针.因此可同指针变量一样置初值
8、 3.指针与字符串(字符数组)如:char s=“Its a string”;char*s=”Its a string”;但有区别:如:char*p;/*指向一个字符的指针变量*/p=“Its a string”/*指向字符串的串首址*/scanf(“%s”,p);/*错误,没有为p所指的 对象分配空间*/又如:char s;s=“Its a string”;/*错误s为地址常量*/,17,例:lenth(s)/*计算s 的长度*/char s;int n;for(n=0;sn!=0;n+);return(n);,lenth(s)char*s;int n;for(n=0;*s+!=0;n+);
9、return(n);,#includemain()static char s1=”abcdef”;/*等价于char*s1=“abcded”;*/int string;string=lenth(s1);/*等价于 string=lenth(,18,例:把字符串t 复制到字符串s 中的函数strcpy(s,t)用指针strcpy(s,t)char*s,*t;while(*s+=*t+)!=0);,用数组strcpy(char s,char t)int i;for(i=0;(si+=ti)!=0;);,*(s+i+)=*(t+i),19,二.指针与多维数组 1.二维数组元素的表示 例:int a2
10、3=1,2,3,4,5,6;1)下标表示:元素的地址表示:&aij(取地址)元素的内容表示:aij,2)元素的数组名表示例:int a23=1,2,3,4,5,6;数组名a被看成由元素a0,a i 的一维数组,但a0又可看成包含3个元素a00,a01,a02,一维数 组 a1又可看成包含3个元素a10,a11,a12,一维数组即:,20,根据C语言规定:数组名代表数组的首地址:因此.a 代表二维数组的首址,(即第0行的首址),a+1:代表第一行的首址同理:a0为另一个一维数组的首址(即第0行第0列元素的首址)即:a0是 a1+2是&a12 即:aij元素的地址用数组名表示:aij或*(a+i)
11、+j 与 二维数组地址&aij一样 aij元素值用数组名表示:有以下几种等价形式:*(ai+j)*(*(a+i)+j)(*(a+i)j/*数组名与下标混合表示*/或:*(&a00+2*i+j)/*注:int a23*/,21,例:编程用指针变量输出数组元素的值.main()int a34=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),22,3)指向数组指针变量的定义如:int(*pa)3,a23;/*指针变量pa指向3个元素的数组*
12、/pa=a;/*使pa指向数组a的第0行;*/注:int(*pa)3 与 int*pa3不同,后者为由三个指针组 成的指针数组.例:上例:main()int a34=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”);,23,2.多维数组的指针表示 三维及以上的数组用指针表示比较复杂,一般采用下 标表示元素法比较好;3.指向二维数组的指针变量的使用 1)指针变量指向二维数组的某个元素 定义时:*指针变量=,int a23,*p=a;(或*p=,2
13、4,for(i=0;i2;i+)printf(“”)for(j=0;j3;j+)p=2)指针变量指向二维数组的首地址 定义时:*指针变量=二维数组名*指针变量=&三数组名00 引用时:指针变量=二维数组名 指针变量=&二数组名00 3)指针变量指向二维数组中的某一个一维数组,P=a;(或p=,25,定义时:(*指针变量)m=二维数组名(m为列长)引用时:指针变量=二维数组名 数组元素的地址引用:*(指针变量+行下标)+列下标 数组元素的内容引用:*(*(指针变量+行下标)+列下标)例:上例:main()int a23,(*p)3=a;int i,j;for(I=0;i2;i+)for(j=0;
14、j3;j+)scanf(“%d”,*(p+i)+j);或:*(a+i)+j;for(i=0;i2;i+)printf(“”)for(j=0;j3;j+)printf(“%5d”,*(*(p+i)+j);或:*(*(a+i)+j);,26,三指针数组和命令行处理由指针变量组成的数组1.指针数组说明的一般形式:类型标识符*数组名常量表达式;例:int*a4;,注:1.*a4是指针数组 而(*p)4是指向数组的指针变量 2.指针数组主要用于字符串数组的处理和命令行参 数的处理因为字符串数组中每一个字符串不等长.,27,例:输入一个表示月份的整数,输出该月份的名字 main()int n;char*m
15、onth=“Illegal month“,“Jan.”,“Feb.”,“March”,“April”,”May”,”June”,”July”,“Aug.”,”Sep.”,“Oct.”,”Nov.”,”Dec.”;printf(“Input number of month:n:“);scanf(“%d”,28,2.命令行参数的处理 命令行带有任选变元或参数称为命令行参数.如:cecho hello world/*操作系统下的命令行*/发布命令行的时刻:在操作系统下执行时 如何将命令的参数接收到程序中?方法是:通过函数main(argc,argv)中argc,argv传送给 程序.其中:argc:
16、计算命令行中参数的个数 argv:指针数组:每个元素是指向包含这些参数(字 符串)的指针,如:cecho hello world argc=3 argv0=“echo”argv1=“hello”argv2=“world”,29,参数argc,argv的定义:main(argc,argv)int argc;char*argv;/*或char*argv;).注:1.argc和argv位置不能颠倒 2.argc和argv的初始化,由键入的命令(包括命令字)的个 数决定.,30,例:编一命令行执行程序:cecho what day is today?输出命令行参数:what day is taday?
17、main(argc,argv)int argc;char*argv;while(-argc 0)printf(“%s%c”,*+argv,(argc1)?:n);编译echo.c生成echo.exe 文件,在dos状态下执行 cecho what day is today?显示:what day is today?它告诉我们:可在操作系统状态下,利用程序,接收字符 串,然后处理这些串.例如:输入:cday 2 2001/*设计程序day.c,接收月份,年份,显示该月的天数*/,31,四:指向指针的指针变量 定义形式:类型标识符*标识符 例:char*p;,相当于*(*p)其中:*p是指针变量的
18、说明,它说明了一个指向字符型数 据的指针变量 前*()星号表示指针变量p是指向一个字符型指针 变量的指针变量(指针变量的嵌套定义),注:访问内容时,需要二次间址操作:用*p表示:*p是间 接指向对象的地址,而*p是p间接指向的对象的值.,32,例:#include main int i,a5,*num5,*p;printf(“input integer 5:n“);for(i=0;i5;I+)numi=,输入:integer 5:输出:,33,.指针与函数 一.指针变量作为函数参数 1.指针变量作为函数形参可改变对应实参的值(传地址),如:main()int a=5;i=3,out;out=c
19、hanger(,注:除数组名外,任何以 地址传递的实参变 量必须在变量名前 加上&符号,表示传 地址,在被调用函数 中形参要说明为指针,34,2.通过指针参数可以从被调用参数中返回多个值例.求10个整数中奇数和偶数的个数 void count(int x,int p1,int p2)if(x%2!=0)+*p1;else+*p2;main()int i,j,sum1=0,sum2=0;for(i=0;i=10;+i)scanf(“%d”,35,2.指针作形参,对应实参的形式void sort(int*v,int n)/*v 和*v都是数组指针变量*/.,调用函数 int a10,*p;p=.,
20、36,2)形参说明为指向数组元素的指针,实参为数组元素的 地址或指向元素的指针变量.如:void f(int*p,int size).调用函数 int a23;.f(a0,2*3);/*或&a00*/.,37,3)形参说明为指向下一级数组的指针,实参为下一组数 组的指针,或指向下一级数组的指针变量.如:void f(int(*pa)3,int size).调用函数:int a23;f(a,2);,或 int a23,(*p)3;p=a;f(p,2);,C语言中:函数不能返回数组,函数,结构,联合类型的值,但可以用返回指向此类数据的指针的方法实现.,38,二.指向函数的指针变量(函数指针)定义形
21、式:类型标识符(*指针变量名)();例:int(*p)();/*与数组指针定义类似:char(*p)*/说明:1.p是指向一个函数的指针变量,(指向该函数名代 表的入口地址送指针p),此函数返回int类型的值 2.用函数指针变量调用函数时,用函数名送入p中 即可.作用:利用函数指针将函数名传给一个函数.,39,例:求a,b中的最小数的程序.1.一般函数调用main()int a,b,c;scanf(“%d%d”,2.用函数指针调用main()int a,b,c;int(*p)();scanf(“%d%d”,注:函数指针作为函数,函数名作 为形参,实现将函数名作为参 数传给其他函数的目的,40,
22、例:有函数max,min,mean 分别起两个整数中最大,最小,平均值.max(int x,int y)int z;if(xy)z=x;else z=y;return(z);min(int x,int y)int z;if(xy)z=x;else z=y;return(z);mean(int x,int y)/*转右边*/,int z;z=(x+y)/2;return(z);main()int a,b,c,e,d;scanf(“%d%d”,41,通过函数指针将函数名作为参数传给其他函数,便能创造出功能很强的高级函数系统,在大型c程序设计中很有作用定义另一个函数all如下,void all(in
23、t x,int y,func)int(*func)();/*函数名传递*/int z;z=(*func)(x,y);printf(“%dn”,z);main()int a,b;scanf(“%d%d”,42,三.指针函数(与指针数组类似)返回指针的函数定义形式:类型标识符*函数名(参数表);例:int*f(x,y);/*与指针数组类似:int*f10;*/返回值是一个指向整型数据的指针.(可返回数组的首址,结构首址,联合首址,指针变量的地址和变量地址)例,将两个字符串连成一个串,并输出。char*cat(char*p1,char*p2)static char a160,*p;p=a;while
24、(*p1!=0)*p+=*p1+;while(*p2!=0)*p+=*p2+;*p=*p2;return(a);,43,main()char s180,s280;scanf(“%s”,s1);scanf(“%s”,s2);printf(“%sn”,cat(s1,s2);,44,上机题(以下各题全部用指针方法实现和数组方法完成)1.编程:输入15个整数存入一维数组,再按逆序重新存放入 再输出 2.编程:输入一个字符串,按相反次序输出其中的所有字符 3.编程:输入10个整数,将其中最大数和最后一个数交换,最 小数和第一个数交换,然后显示这10个数 4.编程:输入三个字符串.输出其中最长的字符串,(
25、要求:将 求串长编写成函数然后调用),45,练习题将下列函数的数组参数,改写成指针参数,且使函数的功能不变float av(a,n)float a;int n;int i;float s;for(i=0,s=0;in;i+)s=s+ai;return(s/n);,46,1.阅读下列程序写出运算结果unsigned f(unsigned num)unsigned k=1;do k*=num%10;num/=10;while(num);return(k);main()unsigned n=26;printf(“%dn”,f(n);,47,2)char s=”ABCD”;main()char*p;for(p=s;ps+4;p+)printf(“%s”n”,p);,3.编程:输入个整数存入一维数组中,统计其中既能 被整除又能被整除的数的个数(用组数和指针两种 方式做)同时显示这些数在该数组中的下标值 4.编程:输入一个字符串,间隔显示其中的字符(用 指针和数组两种方法做)如:显示:,48,回答下列各题1)x是指向25的指针,printf(“%dn”,+*x);输出什么值 2)int a10=1,2,3,4,5,6,7,8,9,10;p=a;则p+=3;+*p;执行后p指示的对象的值是多少3)执行char a10=“abcd”;*p=a后,*(p+4)的值是多少,