[其它]四川大学c程序课件第8章.ppt
第8章指针,Company Logo,主要内容,8.2 指针变量的定义,计算机基础 教学实验中心,Company Logo,8.1指针概述及定义,计算机基础 教学实验中心,Company Logo,8.2 指针变量的定义,对指针变量的定义包括三个内容:(1)指针类型说明,即定义变量为一个指针变量;(2)指针变量名;(3)变量值(指针)所指向的变量的数据类型。其一般形式为:类型说明符*变量名;这里的*并不是乘法运算符,而表示这是一个指针变量,变量名即为定义的指针变量名,类型说明符表示该指针变量所指向的变量的数据类型。,计算机基础 教学实验中心,Company Logo,8.3 指针变量的引用,计算机基础 教学实验中心,指针变量的引用即使用,使用之前必须赋予确定的值。若使用未经赋值的指针变量将造成系统混乱,甚至导致系统崩溃。,Company Logo,计算机基础 教学实验中心,&取地址运算符形式:&变量名&是单目运算符,其结合性为自右至左,优先级仅低于括号等一级优先的运算符。,8.3 指针变量的引用,Company Logo,指针定义注意事项,计算机基础 教学实验中心,1、在初始化时,必须先定义变量x,再将该变量的地址用取地址运算符赋给指针变量p,而不能颠倒其先后顺序,如以下定义便是错误的:int*p=被赋值的指针变量前不能再加“*”说明符,如写为*p=&a 也是错误的。,Company Logo,指针定义例子,计算机基础 教学实验中心,例8.1 指出以下语句中的错误(0)#define M 99(1)float x,y,*pf;(2)char c,*pc;(3)int a10,*pi1,*pi2;(4)pf=(10)pf=&(x+y),Company Logo,*指针运算符,计算机基础 教学实验中心,取内容运算符*是单目运算符,其结合性为自右至左,用来表示指针变量所指的变量。在*运算符之后跟的变量必须是指针变量 例main()char c,*poniter=/*语句5*/该程序运行的结果为:bb,Company Logo,指针举例,计算机基础 教学实验中心,例8.3main()int a,b,c,d,*p1,*p2;/*语句1*/p1=/*语句7*/,Company Logo,指针举例,计算机基础 教学实验中心,例 8.4 以下程序运行后,x,y,z的值各为多少?main()(1)int x,y,z,l=4,m=6,n=8;(2)int*p1=该程序的运行结果是:x=1y=9z=24,Company Logo,8.4 指针作为函数参数,计算机基础 教学实验中心,函数参数的类型,可是整型、实型、字符型等基本类型,也可以是指针类型 例85#inchlude main()int*p,*q;int m=58;int n=99;void change1();void change2();void change3();p=m:q=n;*比较附试change1函数前后m,n的值*printf(“n调用change1函数之前:m=d n=%d”,m,n);changel(m,n);printf(“n调用change1函数之后:m=d n=%d”,m,n);*比较调试change2函数前后m,n的值*printf(“n调用change2函数之前:m=d n=%d”,m,n);,Company Logo,例85(continue),change2(mn);printf(“n调用change2函数之后:m=d n=%d”,m,n);*比较调试change3函数前后m,n的值*printf(“m调用change3函数之前:m=d n=%d”,m,n);change3(p,q);printf(“n调用ehg3函数之后:m=d n=%d”,m,n);Void changel(int m,int n)m=1n=1printf(“n在函数change1中:m=%d n=%d”,m,n);,计算机基础 教学实验中心,Void change2(int*pm,int*pn)*pm=1;*pn=l:printf(“n在函数change2中:*pm=%d*pn=%d”,*pm,*pn);Void change3(int*pm,int*pn)int i;int j;i=2;j=2;pm=,Company Logo,上面这段程序包含三个函数运行情况如下:调用change1函数之前:m=58 n=99 在函数change1中:m=1 n=1 调用change1函数之后:m:58 n=99 调用change2函数之前:m=58 n=99 在函数change2中:*pm=1*pn=1 调用change2函数之后:m=1 n=1 调用ck3函数之前:m=1 n=1 在函数change3中:*pm=2*pn=2 调用change3函数之后:m=1 n=1,计算机基础 教学实验中心,Company Logo,8.5指针数组,计算机基础 教学实验中心,8.5.1指向数组元素的指针变量指向数组的指针变量的定义形式:int x100,y;int*p;整型变量y,整型数组x,指向整型的指针变量p。指针变量p并没有指向任何变量,它既可以指向整型的变量,如y,也可指向整型的数组x,这取决于把哪个变量的地址赋给p让p指向数组x可以写为:p=x;或p=x0;,Company Logo,8.5.2利用指针访问数组元素,当指针变量指向某个数组,在访问数组时就有两种方式:下标法和指针法。如:int*p,m20;p=m;指针法访问数组是用指向数组的指针变量加上某个数组元素的序号,得到该数组元素的地址后作指针运算*,即可表示该数组元素,如p+i为mi的地址,而*(p+i)就代表mi。指向数组的指针变量也可带下标,如pi,即pi*(p+1)mi*(m+i),代表等价。,计算机基础 教学实验中心,Company Logo,例8.6用指针法和下标法访问数组,#include main()static int m10=0,1,2,3,4,5,6,7,8,9;int i;int*p;p=m;for(i=0;i=9;i+)printf(ni=%d,mi=%d,*(m+i)=%d,pi=%d,*(p+i)=%d,i,mi,*(m+i),pi,*(p+i);printf(,计算机基础 教学实验中心,Company Logo,8.5.4数组名及指向数组的指针变量作函数参数,在函数中,数组名可以作函数的参数 当数组名作函数的参数时,由于数组名代表该数组的首地址即在调用函数时,将该数组的首地址传给形参,形参和实参共同指向一段内存,形参并未开辟新的存储单元,计算机基础 教学实验中心,Company Logo,例 二分查找算法,用binary search(二分查找算法)从一个已排好序的数列中查找一个数,判定此数是否属于该数列。int b_search(m,num,key)int m,num,key;int l,h,mid;l=0;h=num-1;while(lmmid)l=mid+1;else return(mid);return(-1);,计算机基础 教学实验中心,Company Logo,例二分查找算法,main()static int b=10,12,13,14,25,34,72,88,100;int k,i,j;printf(The arranged array is:n);for(i=0;i9;i+)printf(%d,bi);printf(n);printf(Please input the key number which is to be searched:n);scanf(%d,计算机基础 教学实验中心,Company Logo,8.5.4数组名及指向数组的指针变量作函数参数,计算机基础 教学实验中心,对这个程序可以作一些改动,将bin_search函数中的形参m用指针代替,实参为数组名b,传给形参指针变量,使形参指向数组b的首地址。int bin_search(m,num,key)int*m,num,key;int1,h,mid;1=0;h=num-1while(1*(m+mid)1=mid+h;elsereturn mid;/*找到了*/return-1;,Company Logo,例8.9,计算机基础 教学实验中心,阅读下列程序,在编号(1)、(2)、(3)、(4)处分别填入合适的语句,使程序完整。说明:下面的程序用invert函数按逆序重新放置a数组中元素,a数组的值由用户用健盘输入。#include#define LEN 10main()int aLEN,i;void invert();for(i=0;iLEN;i+)(1)(“%d”,Company Logo,例8.9,void invert(x,m,n)int*x,m,n;int k;if(mn)k=(3);*(x+m)=*(x+n);*(x+n)=k;invert(x,(4),n-1);,计算机基础 教学实验中心,Company Logo,例8.9,分析:该程序的目的是:用户从键盘上输入LEN个数(10个数),存在a数组中。然后调用invert函数,把数组a中的元素首尾依次对调,如图8.14所示:a0与a9对调,a1与a8对调,直到全部元素对调为止。在main函数中,通过键盘输入数组的值,这里笫(1)个空就应该填上scanf。main函数中调用invert函数,以便将a数组首尾颠倒,invert函数的形参为指向整型变量的指针x,把数组a的地址传给它,使x指向a,所以(2)应为a。在invert函数中,形参x指向数组a,m和n分别指向需要交换的二个数组元素的下标当n、n为止,如图所示,所以第4个空应该填m+1。,计算机基础 教学实验中心,Company Logo,8.6指针运算,1指针变量的赋值运算 指针变量定义之后,并不能象其他变量那样随意对它赋值。char c1,*q;定义q为指向字符型变量的指针,表明q可以存放某个字符型变量的地址,但如果用下列语句给q赋一个地址值:q=2000;则是不可以的 赋值的形式有如下几种:,计算机基础 教学实验中心,Company Logo,(1)利用取地址运算符,计算机基础 教学实验中心,Company Logo,(2)同类型的指针变量可以进行赋值运算,其结果是二者同时指向一个变量,如:float m,*p1,*p2;p1=&m;p2=p1;这里*p1,*p2与m的值相等,计算机基础 教学实验中心,Company Logo,(3)利用强制类型转换运算可以实现不同类型指针的相互赋值 如果在不同类型的指针间进行相互赋值,往往会导致编译时出现错误。有时若一定要使不同类型的指针变量进行交叉赋值,则必须用强制运算符,如:char cl,*p1;double x,*p2;如果一定要用pl指向x,则必须这样写:p1=(char*)(char*)&x实现强制类型转换,把变量x的地址强制换成char类型数据的地址,这样两边的类型一致了,就可以进行赋值运算。,计算机基础 教学实验中心,Company Logo,(4)对字符指针变量赋初值可采用字符串赋值的形式,如:char*m;m=“This is a pen”;使m指向“This is a pen”字符串,m此时的值为该字符串第零个元素的地址,即T这个字符存放在内存中的地址。,计算机基础 教学实验中心,Company Logo,8.6.2 指针变量的*运算-间接引用对指针变量的间接引用是通过用间接运算符*来实现的,由于*(间接运算符)级别仅次于括号,所以对指针变量的间接引用往往可作为一个整体来分析。如:main()int k=2,*pk=由于*pk等价于k,*pm等价于m.所以,*pk*(*pm)即为k*m,(24)值为8。,计算机基础 教学实验中心,Company Logo,例8.13 分析以下程序执行后的结果。(1)#include stdio.h(2)main()(3)(4)static int m5=7,4,6,3,10;(5)int i,j,*p;(6)i=10;(7)p=(11),计算机基础 教学实验中心,Company Logo,8.6.3、指针的加减运算对指针变量进行加上或减去一个整数称为移动指针,使指针变量指向相邻的存储单元。只有当指针指向一段连续的内存单元时,指针的移动才有意义。除了上述加减运算外,指针变量不能作其他任何的算术运算,如指针变量的乘除,取模运算等。,计算机基础 教学实验中心,Company Logo,8.7 指向字符串的指针,通常用字符数组表示字符串,如:char s=“This is a book”;若用字符指针来表示,则应写为:char*p=“This is a book”;或者:char*p;p=“This is a book”,计算机基础 教学实验中心,Company Logo,8.7 指向字符串的指针,例:(1)#include(2)#include(3)main()(4)(5)char s=“Sichuan University”;(6)char*p;(7)int*q;(8)int a 10=1,2,3,4,5,6,7,8,9,10;(9)p=“Sichuan University”;(10)q=a;(11)printf(“%s,%s”,p,s);(12)printf(“%s,%s”,q,a);(13)在上述程序中,第(11)条语句输出如下结果:Sichuan University,Sichuan University而第(12)条语句则会出错,因为通过字符数组名或字符指针变量可以输出整个字符数组名或字符串,如语句(11),而对于数值型数组,是不能这样做的,如第(12)条语句就是错误的。,计算机基础 教学实验中心,Company Logo,8.7 指向字符串的指针,字符指针变量和字符数组的区别:(1)字符指针变量中存放的是字符串的首地址,不是将字符串放到字符指针变量中,而字符数组则由若干数组元素组成,每个元素放一个字符。(2)赋初值的方式不同:对于字符指针char*s=“This is a pen”;等价于char*s;s=“This is a pen”;对于字符数组初始化:static char m30=“This is a pen”;不等价于static char m30;m=“This is a pen”;因为数组可以在变量定义时整体赋初值,除此之外不能用赋值语句给其赋值。,计算机基础 教学实验中心,Company Logo,8.7 指向字符串的指针,(3)赋值方式不同对于字符数组,赋值方式是用赋值语句给其每一个元素赋值一个字符,而不能将整个字符串赋给它。若一定要在语句中将整个字符串赋给一个字符数组,则必须用strcpy函数来实现,如:char s30;s=“Sichuan university”;是错误的,应该用下方式进行赋值。s0=S;s1=i;s2=c;s17=y;或用:strcpy(s,“Sichuan university”);,计算机基础 教学实验中心,Company Logo,8.7 指向字符串的指针,char*s;s=“Sichuan university”;是正确的。字符指针之间的相互赋值与其它变量无异,如:char*s1=“Sichuan university”;char*s2;s2=s1;就可将s1的值赋给了s2。,计算机基础 教学实验中心,Company Logo,例8.15-,+与字符指针的综合应用,#include main()char s=sichuanuniversity;int*pc=s;printf(pc=%d*pc=%cn,pc,*pc);printf(pc=%d*pc=%cn,pc,+(*pc);printf(pc=%d*pc=%cn,pc,+*pc);printf(pc=%d*pc=%cn,pc,*pc);printf(pc=%d*pc=%cn,pc,*(+pc);printf(pc=%d*pc=%cn,pc,*+pc);printf(pc=%d*pc=%cn,pc,*pc-);printf(pc=%d*pc=%cn,pc,*pc+);程序运行结果如图。,计算机基础 教学实验中心,Company Logo,计算机基础 教学实验中心,例8.15,