指针计算机基础知识

上传人:枫** 文档编号:586665884 上传时间:2024-09-05 格式:PPT 页数:142 大小:959.50KB
返回 下载 相关 举报
指针计算机基础知识_第1页
第1页 / 共142页
指针计算机基础知识_第2页
第2页 / 共142页
指针计算机基础知识_第3页
第3页 / 共142页
指针计算机基础知识_第4页
第4页 / 共142页
指针计算机基础知识_第5页
第5页 / 共142页
点击查看更多>>
资源描述

《指针计算机基础知识》由会员分享,可在线阅读,更多相关《指针计算机基础知识(142页珍藏版)》请在金锄头文库上搜索。

1、指针的故事指针的故事“该程序执行了非法操作,即将关闭”这种错误几乎全是由指针和数组导致的黑客攻击服务器利用的bug绝大部分都是指针和数组造成的主要内容主要内容 1.1.地址和指针的概念地址和指针的概念 2.2.变量的指针和指向变量的变量的指针和指向变量的 指针变量指针变量 3.3.数组与指针数组与指针 4.4.字符串与指针字符串与指针 5.5.指向函数的指针指向函数的指针 6.6.返回指针值的函数返回指针值的函数 7.7.指针数组和指向指针的指针指针数组和指向指针的指针 地址内存中每一个字节的存贮单元都有一个编号,这个编内存中每一个字节的存贮单元都有一个编号,这个编号就是号就是“地址地址” 。

2、如果在程序中定义了一个变量,。如果在程序中定义了一个变量,在对程序进行编译时,系统就会给这个变量分配存贮在对程序进行编译时,系统就会给这个变量分配存贮单元。单元。 .按变量地址存取变量值的方式称为按变量地址存取变量值的方式称为“直接访问直接访问”方式方式 (,);,); (,);,); ; 将每个数据的将每个数据的首字节地址首字节地址作为该数据的作为该数据的地址地址。 内内内内存存存存是是是是一一一一个个个个连连连连续续续续编编编编址址址址的的的的空空空空间间间间,每每每每一一一一个个个个存存存存储储储储单单单单元元元元都都都都有一个固定的编号,这个编号称为有一个固定的编号,这个编号称为有一个

3、固定的编号,这个编号称为有一个固定的编号,这个编号称为地址地址地址地址。 地地地地址址址址是是是是一一一一个个个个无无无无符符符符号号号号整整整整数数数数(通通通通常常常常用用用用1616进进进进制制制制数数数数),其其其其字长与主机相同字长与主机相同字长与主机相同字长与主机相同例如:例如:已已定定义义了了一一个个整整型型数数组组d6。设设该该数数组组的的起始地址为起始地址为ee10(d0的地址),的地址),赋值赋值d0=10。数组名是一个数组名是一个常量地址常量地址 , 也为也为ee10 2000 2000 2002 2002 2004 2004用户内存数据区用户内存数据区(1) 求地址运算

4、(求地址运算(&)每每个个变变量量/数数组组都都有有一一个个内内存存地地址址,在在何何地地址一般无法预测。可通过求地址运算得到。址一般无法预测。可通过求地址运算得到。2、求地址运算和访问地址运算、求地址运算和访问地址运算例:例:#include main()int a=1;float b=2.0;double c=3;int d6=-1,-2,-3,-4,-5,-6;printf(“address of a is%xn”,&a);printf(“address of b is%xn”,&b);printf(“address of c is%xn”,&c);printf(“address of

5、d is%xn”,&d);printf(“address of d0 is%xn”,&d0);说明:说明:输出的地址值输出的地址值 用用4位十六进制数表示。位十六进制数表示。&只能施加在变量或数组元素上。只能施加在变量或数组元素上。 &25 &(x+y)均是错误的均是错误的采用访问地址的方法存取数据,速度快,采用访问地址的方法存取数据,速度快,效率高。效率高。 将地址存放在一种将地址存放在一种特殊类型的变量特殊类型的变量中,中,把把对地址对地址的操作转换为的操作转换为对变量对变量的操作。的操作。 v存放地址的变量存放地址的变量指针变量指针变量v指针变量中存放的指针变量中存放的地址地址指针指针n

6、变量地址:变量一定占用一个数据的存储空间,该存储空间的首地址称变量地址。n指针:一个变量的地址称为该变量的指针。n指针变量:若一个变量专用于存放另一个变量 的地址(指针),则该变量称为指 针变量。n指针的对象:指针指向的存储空间中的数据。 指针的概念指针的概念 指针变量是存放地址的变量指针变量是存放地址的变量, ,它的值它的值是指针是指针, ,指针所指向的变量是指针变指针所指向的变量是指针变量所指向的存贮单元中的内容量所指向的存贮单元中的内容指针变量指针变量指针所指指针所指向的变量向的变量10.10.1 .1 定义一个指针变量定义一个指针变量定义指针变量的一般形式为定义指针变量的一般形式为基类

7、型基类型 *指针变量名;指针变量名;int i,j,*pointer_1,*pointer_2;/基类型是基类型是int下面都是合法的定义:下面都是合法的定义:float *pointer_; char *pointer_;指针变量的引用 (1)指针变量只能存放地址,不能将整型数据、字符型数据、实型数据等非地址类型的数据赋值给指针变量。 (2)指针变量只能指向同一类型的变量。 int a=8 ;char h=A; int *p1; char *p2; p1=&a; p2=&h; int a ,*p ; p =&a; *p=5; (1)&a 表表示示取取a变变量量的的地地址址。 *p则则表表示示

8、指指针针变变量量p所指的对象所指的对象a 。 &a5pa*p*&a&*p相关的运算符相关的运算符 取地址运算符:取地址运算符: & 指针运算符(或间接访问运算符):指针运算符(或间接访问运算符): * (2), &为为同级同级运算符,结合性运算符,结合性从从右至左右至左。当执行了当执行了p&a;后,则下列表示是等价后,则下列表示是等价的:的:对象:对象:a= =*p=*&a =*(&a)指针:指针:p= =&a= =&*p = =&(*p) (3)&*p 等价于等价于&a &*p 即即&(*p1)与)与&a等价。等价。(4)p1=&*p;的作用是的作用是p1=&a;(5)(*p )+等价于等价

9、于a+。(6) &与与*互为逆运算互为逆运算,当当 与与&连续在一起连续在一起时,具有抵消作用时,具有抵消作用:*&a= =a ,&*p= =p .7、指针变量的赋值运算指针变量的赋值运算j用取地址运算符用取地址运算符(&) 将一个变量的地址赋给一个指针将一个变量的地址赋给一个指针变量。变量。 int i, p ; i=3; p=&i; 将一个指针变量赋给另一个同类型的指针变量。将一个指针变量赋给另一个同类型的指针变量。int i , pi , pj ;pi=&i ;pj=pi ;作用是使作用是使 pi , pj 都指向变量都指向变量 i。 pii pj&i&i 给指针变量给指针变量(pi)赋

10、赋“空空”值:值:a. pi=NULL;b. pi=0c. pi=0 在定义一个变量时,将变量的指针在定义一个变量时,将变量的指针(即地址即地址) 直接赋给直接赋给指针变量:指针变量:int x, p=&x;可以用赋值语句使一个指针变量得到另一个变可以用赋值语句使一个指针变量得到另一个变量的地址,从而使它指向一个与基类型相同的变量。量的地址,从而使它指向一个与基类型相同的变量。例如:例如:pointer_;pointer_;在定义指针变量时要注意两点:在定义指针变量时要注意两点:(1)指针变量前面的指针变量前面的“*”,表示该变量的类型为指针型,表示该变量的类型为指针型变量。变量。(2)例例:

11、 float *pointer_1;(3)指针变量名是指针变量名是pointer_1 ,而不是,而不是* pointer_1 。 (4)(2) 在定义指针变量时必须指定基类型。在定义指针变量时必须指定基类型。(5) 需要特别注意的是,只有整型变量的地址才能放到需要特别注意的是,只有整型变量的地址才能放到指向整型变量的指针变量中。下面的赋值是错误的指向整型变量的指针变量中。下面的赋值是错误的 (6) float a; (7) int * pointer_1; (8) pointer_1=&a; 10.2.2 10.2.2 指针变量的引用指针变量的引用 1.给指针变量赋初值给指针变量赋初值 int

12、 *p,*q; int a=10; (1)q=&a; 或或 (2) p=q;/让让p指向指向q所指向的存贮单元所指向的存贮单元aq1010.2.2 10.2.2 指针变量的引用指针变量的引用 1.给指针变量赋初值给指针变量赋初值 int *p,*q; int a=10; (1)q=&a; 或或 (2) p=q;/让让p指向指向q所指向的存贮单元所指向的存贮单元aq1010.2.2 10.2.2 指针变量的引用指针变量的引用 1.给指针变量赋初值给指针变量赋初值 int *p,*q; int a=10; (1)q=&a; 或或 (2) p=q;/让让p指向指向q所指向的存贮单元所指向的存贮单元a

13、qp10注意注意:指针变量中只能存放地址(指针),不指针变量中只能存放地址(指针),不要将一个整数(或任何其他非地址类型的要将一个整数(或任何其他非地址类型的数据)赋给一个指针变量。数据)赋给一个指针变量。2.访问指针变量所指向的变量访问指针变量所指向的变量printf(“%d”,*p);说明说明:(1)定义指针变量后定义指针变量后,变量没指向任何存贮单元变量没指向任何存贮单元,要通过赋值要通过赋值语句来确定它所指向的存贮单元语句来确定它所指向的存贮单元(2)&,*的优先级相同的优先级相同,结合方向自右向左结合方向自右向左,为互逆操作为互逆操作&*pp*&a a(3)(*p)+与与*p+的区别

14、的区别前者是为前者是为p所指向的变量所指向的变量+1,后者满足右结合后者满足右结合,p+后执行后执行*操作操作,但但+是后加是后加,所以先使用所以先使用*p的值的值,然后再对然后再对p进行进行+1操作操作*(+p)?例例10.1通过指针变量访问整型变量通过指针变量访问整型变量#includevoidmain()inta,b;int*pointer_1,*pointer_2;a=100;b=10;pointer_1=&a;/*把变量把变量a的地址赋给的地址赋给pointer_1*/pointer_2=&b;/*把变量把变量b的地址赋给的地址赋给pointer_2*/printf(%d,%dn,a

15、,b);printf(%d,%dn,*pointer_1,*pointer_2);10010例例10 . 2 输入和两个整数,按先大后小的顺序输出输入和两个整数,按先大后小的顺序输出 和。和。#includemain()int a,b,*p1,*p2,*p;scanf(%d%d,&a,&b);p1=&a;p2=&b;if (ab) p=p1;p1=p2;p2=p;printf(*p1=%d,*p2=%dn,*p1,*p2);printf(a=%d,b=%dn,a,b);例例10 . 2 输入和两个整数,按先大后小的顺序输出输入和两个整数,按先大后小的顺序输出 和。和。#includemain(

16、)int a,b,*p1,*p2,*p;scanf(%d%d,&a,&b);p1=&a;p2=&b;if (ab) p=p1;p1=p2;p2=p;printf(*p1=%d,*p2=%dn,*p1,*p2);printf(a=%d,b=%dn,a,b);a,b的值没发生变化的值没发生变化!p=p1; p1=p2;p2=p;&ap=p1; p1=p2;p2=p;&a&bp=p1; p1=p2;p2=p;&a&b&ap=p1; p1=p2;p2=p;&b&ap=p1; p1=p2;p2=p;*p1=9, *p2=5a=5, b=910.10.3 .3 指针变量作为函数参数指针变量作为函数参数例例

17、10 . 3 交换两个变量的值交换两个变量的值 #includemain()void swap(int *p1,int *p2); int a,b; int *pointer_1,*pointer_2; scanf(%d%d,&a,&b); pointer_1=&a; pointer_2=&b;swap(pointer_1,pointer_2); printf(%d %dn,a,b);void swap(int *p1,int *p2)int temp;temp=*p1;*p1 = *p2;*p2 =temp;void swap(int *p1,int *p2)int temp;temp=*p

18、1;*p1 = *p2;*p2 =temp;void swap(int *p1,int *p2)int temp;temp=*p1;*p1 = *p2;*p2 =temp;void swap(int *p1,t *p2)int temp;temp=*p1;*p1 = *p2;*p2 =temp;如果将swap函数做如下修改:void swap(int *p1,int *p2)int *temp; temp=p1; p1=p2; p2 =temp;如果将swap函数做如下修改:void swap(int *p1,int *p2)int *temp; temp=p1; p1=p2; p2 =tem

19、p;没有实现交换操作没有实现交换操作!void swap(int *p1,int *p2)int *temp; temp=p1; p1 = p2; p2 =temp;void swap(int *p1,int *p2)int *temp; temp=p1; p1 = p2; p2 =temp;void swap(int *p1,int *p2)int *temp; temp=p1; p1 = p2; p2 =temp;&a&b9 59 5 59使用指针做形参的说明如果要通过函数调用得到如果要通过函数调用得到n个要改的值个要改的值,要经要经过以下步骤过以下步骤:(1)主函数中设主函数中设n个变量

20、个变量,并用并用n个指针变量分个指针变量分别指向它们别指向它们(2)用指针变量作形参用指针变量作形参(3)通过形参指针变量通过形参指针变量,改变改变n个实参的值个实参的值(4)主调函数中使用这些改变了值的变量主调函数中使用这些改变了值的变量上节课小结1.指针与指针变量指针与指针变量2.指针所指向的变量指针所指向的变量3.用指针访问其所指向的变量用指针访问其所指向的变量4.用指针变量做为函数的形参用指针变量做为函数的形参int*p,i;p=&i;*pi,*pvoidswap(int*p,int*q)例例10. 输入输入, 3个整数,按从大到小顺序输出个整数,按从大到小顺序输出#include v

21、oid main() void exchange(int *q1, int *q2, int *q3); int a,b,c,*p1,*p2,*p3; scanf(%d%d%d,&a,&b,&c); p1=&a;p2=&b;p3=&c; exchange (p1,p2,p3); printf(n%d,%d,%dn,a,b,c); void exchange(int *q1, int *q2, int *q3) void swap(int *pt1, int *pt2); if(*q1*q2) swap(q1,q2); if(*q1*q3) swap(q1,q3); if(*q2*q3) swa

22、p(q2,q3); void swap(int *pt1, int *pt2) int temp; temp=*pt1; *pt1=*pt2; *pt2=temp; 10.3 数组与指针 一个变量有地址,一个数组包含若干元素,每个一个变量有地址,一个数组包含若干元素,每个数组元素都在内存中占用存储单元,它们都有相数组元素都在内存中占用存储单元,它们都有相应的地址。指针变量既然可以指向变量,当然也应的地址。指针变量既然可以指向变量,当然也可以指向数组元素(把某一元素的地址放到一个可以指向数组元素(把某一元素的地址放到一个指针变量中)。所谓指针变量中)。所谓数组元素的指针就是数组元数组元素的指针就

23、是数组元素的地址素的地址。 定义一个指向数组元素的指针变量的方法,与以定义一个指向数组元素的指针变量的方法,与以前介绍的指向变量的指针变量相同。前介绍的指向变量的指针变量相同。例如:例如:intint a10 a10; intint *p *p; a0; 10.3.1 10.3.1 指向数组元素的指针指向数组元素的指针p=a;p+i&ai*( )10.10. .通过指针引用数组元素通过指针引用数组元素引用一个数组元素,可以用:引用一个数组元素,可以用:()() 下标法,如下标法,如ai形式或形式或pi(但要先执行但要先执行p=a );()() 指针法,如指针法,如*(a+i)或或*(p+i)。

24、其中是数组名,。其中是数组名,是指向数组元素的指针变量,其初值。是指向数组元素的指针变量,其初值。( 3 )p=a; p+,用用*p访问数组元素访问数组元素 说明说明: ( 1 )指针可以实现指针可以实现+和和-操作操作,但数组名不可以但数组名不可以,因为数组名是一个指针常量因为数组名是一个指针常量 ( 2 )p+代表指针移向下一个数组元素代表指针移向下一个数组元素,而不是一而不是一个存贮单元个存贮单元,int型下移两个单元型下移两个单元,float型下移型下移4个个单元单元假设有一个数组,整型,有个元素。要输出假设有一个数组,整型,有个元素。要输出各元素的值有三种方法:各元素的值有三种方法:

25、 (1)下标法。下标法。(2) 通过数组名计算数组元素地址,找出元素通过数组名计算数组元素地址,找出元素的值。的值。(3) 用指针变量指向数组元素。用指针变量指向数组元素。例例10.5 输出数组中的全部元素。输出数组中的全部元素。 (1)下标法。下标法。main()int a10;int i;for(i=0;i10;i+) scanf(“%d”,&ai);printf(n);for (i=0;i10;i+) printf(“%d”,ai); (1)下标法。下标法。main()int a10;int i, *p;for(i=0;i10;i+) scanf(“%d”,&ai);printf(n);

26、p=a;for (i=0;i10;i+) printf(“%d”,pi); (2) 通过数组名计算数组元素地址,找出元素的值。通过数组名计算数组元素地址,找出元素的值。main()int a10; int i;for(i=0;i10;i+) scanf(“%d”,&ai);printf(n);for (i=0;i10;i+) printf(“%d”,*(a+i); (2) 通过数组名计算数组元素地址,找出元素的值。通过数组名计算数组元素地址,找出元素的值。main()int a10; int i ,*p;for(i=0;i10;i+) scanf(“%d”,&ai);printf(n);p=a

27、;for (i=0;i10;i+) printf(“%d”,*(p+i); (3) 用指针变量指向数组元素。用指针变量指向数组元素。main()int a10; int *p; int i;for(i=0;i10;i+) scanf(%d,&ai);for(p=a;p(a+10);p+) printf(%d,*p);(4)用-操作实现逆向输出元素voidmain()inta10;int*p;inti;for(i=0;i=a;p-)printf(%5d,*p);例例10. 通过指针变量输出数组的个元素。通过指针变量输出数组的个元素。 main()int a10, *p, i; p=a;for(i

28、=0;i10;i+) scanf(%d,p+);for(i=0;i10;i+,p+) printf(%dn,*p);main()int a10, *p, i; p=a;for(i=0;i10;i+) scanf(“%d”,p+);p=a;for(p=a;i10;i+,p+) printf(“%d”,*p);10.3.3 10.3.3 用数组名作函数参数用数组名作函数参数在第在第8章章8.7节中介绍过可以用数组名作函数的参数节中介绍过可以用数组名作函数的参数如:如: void main()() (int arr ,int ); int array; (array,);,); void (int

29、arr,int ) 例例10 将数组中个整数按相反顺序存放。将数组中个整数按相反顺序存放。main()inta10=1,2,3,4,5,6,7,8,9,10;inti;inv(a,10);for(i=0;i10;i+)printf(%3d,ai);printf(n);void inv(int x,int n)int *i,*j;int temp,m;m=n/2;i=x; j=x+n-1;for(;ix+m;i+,j-)temp=*i;*i=*j;*j=temp;对刚才的程序可以作一些改动。将函数对刚才的程序可以作一些改动。将函数inv中中的形参改成指针变量。的形参改成指针变量。 void in

30、v(int *x,int n)int temp,*i,*j,m=(n-1)/2;i=x;j=x+n-1;for(;i=x+m;i+,j-) temp=*i; *i=*j; *j=temp;如果有一个实参数组,想在函数中改变此数如果有一个实参数组,想在函数中改变此数组中的元素的值,实参与形参的对应关系有组中的元素的值,实参与形参的对应关系有以下种情况:以下种情况: (1) 形参和实参都用数组名,如:形参和实参都用数组名,如:void main()() void (int ,int ) int ; (,);(,); (2) 实参用数组名,形参用指针变量。如:实参用数组名,形参用指针变量。如:voi

31、d ()() void (int *,int )int ; (,);(,); (3)实参形参都用指针变量。例如:实参形参都用指针变量。例如:void main()() void (int *,int )int , *p=a; (p,);,); (4) 实参为指针变量,形参为数组名。如:实参为指针变量,形参为数组名。如: void main()() void (int x ,int ) ,*p=a; (p,);,); 例10. 从10个数中找出其中的最大值和最小值intmax,min;voidmax_min(intarray,intn)int*p,*array_end;max=min=*arra

32、y;array_end=array+n;for(p=array+1;pmax)max=*p;elseif(*pmin)min=*p;main()inta10=6,7,8,1,2,3,4,5,9,10;max_min(a,10);printf(max=%3d,min=%3dn,max,min);10.3.4 10.3.4 多维数组与指针多维数组与指针 用指针变量可以指向一维数组中的用指针变量可以指向一维数组中的元素,也可以指向多维数组中的元元素,也可以指向多维数组中的元素。但在概念上和使用上,多维数素。但在概念上和使用上,多维数组的指针比一维数组的指针要复杂组的指针比一维数组的指针要复杂一些。一

33、些。 复习一维数组与指针之间的关系inta10,*p;p=a;p=&ai=a+i;*p=*(a+i)=ai;pp+i a1. 1. 多维数组元素的地址多维数组元素的地址先回顾一下多维数组的性质先回顾一下多维数组的性质,可以认为二可以认为二维数组是维数组是“数组的数组数组的数组”,例,例 :定义定义int a34=1,3,5,7,;则二维数组则二维数组a是由是由3个一维数组所组成的。个一维数组所组成的。a00a01a02a03a10a11a12a13a20a21a22a23a0a1a2aa+1a+2a+i = &ai(1)a,a+1,a+2分别代表分别代表&a0,&a1,&a2a00a01a02

34、a03a10a11a12a13a20a21a22a23a0a1a2a+i = &ai(2)a0,a1,a2分别代表分别代表&a00,&a10,&a20a00a01a02a03a10a11a12a13a20a21a22a23a0a1a2aa+1a+2a+i = &aia2+1,a2+2分别代表分别代表&a21,&a22ai+j(3)&aija00a01a02a03a10a11a12a13a20a21a22a23a0a1a2aa+1a+2a+i = &ai*(a+i)+j&aij*(a+i) = aiai+ja00a01a02a03a10a11a12a13a20a21a22a23a0a1a2aa+

35、1a+2a+i = &ai*(a+i)+j(4)&aij*(a+i) = aia00a01a02a03a10a11a12a13a20a21a22a23a0a1a2aa+1a+2a+i = &ai*(*(a+i)+j)(5)*(&aij)*(a+i) = aia00a01a02a03a10a11a12a13a20a21a22a23a0a1a2aa+1a+2a+i = &ai*(*(a+i)+j)(5) aij*(a+i) = aia00a01a02a03a10a11a12a13a20a21a22a23a0a1a2aa+1a+2a+i与与*(a+i)有什么区别有什么区别?小结(1)a,a+1,a+

36、2分别代表分别代表&a0,&a1,&a2(2)a0,a1,a2分别代表分别代表&a00,&a10,&a20(3)ai+j代表代表&aij(4)*(a+i)+j代表代表&aij(5)*(*(a+i)+j)代表代表aijai从形式上看是一维数组的第从形式上看是一维数组的第i个分量个分量,但当但当a为二维为二维数组时数组时,ai只代表一个地址只代表一个地址2.指向二维数组的指针变量(1)用指针变量输出数组元素的值用指针变量输出数组元素的值main()inta34=1,2,3,4,5,6,7,8,9,10,11,12;int*p;/printf(%on%on%on%on,a,a0,&a0,&a00);

37、for(p=a0;pa0+12;p+)if(p-a0)%4=0)printf(n);printf(%4d,*p);用普通的指针变量输出数据元素时用普通的指针变量输出数据元素时,要先二维数组要先二维数组序列化为一维序列化为一维,然后再输出然后再输出.接下来定义提向一维接下来定义提向一维数组的指针变量数组的指针变量.(2)指向一维数组的指针变量指向一维数组的指针变量的声明形式:指向一维数组的指针变量的声明形式:int(*p)4;p可以指向由四个分量组成的一维数组可以指向由四个分量组成的一维数组,p每每次次+1,移动的单元数是一维数组所占的单元移动的单元数是一维数组所占的单元数数,它等同于二维数组的

38、行移动它等同于二维数组的行移动.因此,因此,p等等价于二维数组。价于二维数组。例,输出二维数组中任一行任一列元素的值例,输出二维数组中任一行任一列元素的值main()inta34=1,2,3,4,5,6,7,8,9,10,11,12;inti,j,(*p)4;p=a;scanf(%d%d,&i,&j);printf(%dn,*(*(p+i)+j);3.用指向数组的指针作函数参数一维数组名可以作函数参数,多维数组名一维数组名可以作函数参数,多维数组名也可以做为参数传递。用指针变量做形参也可以做为参数传递。用指针变量做形参时接收实参数组名传递来的地址时,有两时接收实参数组名传递来的地址时,有两种方

39、法:种方法:u指向变量的指针变量,实参为指向变量的指针变量,实参为*数组名数组名u指向一维数组的指针变量,实参为指向一维数组的指针变量,实参为数组名数组名例,有一个班有例,有一个班有3名学生,名学生,4门课程,计算总平门课程,计算总平均分以及查找第均分以及查找第n个学生的成绩。个学生的成绩。main()voidaverage(float*p,intn);voidsearch(float(*p)4,intn);floatscore34=65,67,70,60,80,87,90,81,90,99,100,98;average(*score,12);search(score,2);voidavera

40、ge(float*p,intn)inti;float*p_end;floatsum=0.0,avg;p_end=p+n-1;for(;pp_end;p+)sum=sum+(*p);avg=sum/n;printf(average=%5.2fn,avg);voidsearch(float(*p)4,intn)inti;printf(thescoreofnumber%dstudentisn,n);for(i=0;i4;i+)printf(%5.0f,*(*(p+n)+i);例,在上题的基础上,查找有一门以上课程不及格的学生,打印出他们的全部课程成绩voidsearch(float(*p)4,int

41、n)inti,j,flag;for(i=0;in;i+)flag=0;for(j=0;j4;j+)if(*(*(p+i)+j)60)flag=1;if(flag=1)printf(number%dstudentfails:n,i);for(j=0;j4;j+)printf(%5.1f,*(*(p+i)+j);printf(n);/if/for 10. 字符串与指针1.字符串的表示形式字符串的表示形式C语言用两种方式处理字符串语言用两种方式处理字符串字符型数组字符型数组main()charstr=”IloveChina”;printf(“%sn”,str);字符指针字符指针main()char*

42、str=”IloveChina”;printf(“%sn”,str);说明:说明:(1)char*str=”IloveChina”;等价于等价于char*str;str=”IloveChina”;把字符串的首地址赋给把字符串的首地址赋给str,不等价于不等价于char*str;*str=”IloveChina”;(2)用字符型指针变量或字符数组表示用字符型指针变量或字符数组表示的字符串可以用的字符串可以用%s整体输入输出,其整体输入输出,其他类型的指针变量或数组不可以,只他类型的指针变量或数组不可以,只能逐个分量操作。能逐个分量操作。例,将字符串例,将字符串a复制到字符串复制到字符串bmain

43、()chara15=Iamaboy;charb15;inti;for(i=0;*(a+i)!=0;i+)*(b+i)=*(a+i);*(b+i)=0;for(i=0;bi!=0;i+)printf(%c,bi);/printf(%s,b);用指针变量处理上题用指针变量处理上题main()chara=”Iamaboy”,b20,*p1,*p2;inti;p1=a;p2=b;for(;*p1!=0;p1+,p2+)*p2=*p1;*p2=0;printf(“%s”,b);2.字符串指针作函数参数字符串数组或指针做函数参数可以实现地址传递字符串数组或指针做函数参数可以实现地址传递(1)用字符数组做参

44、数用字符数组做参数voidcopy_str(charfrom,charto)inti=0;while(fromi!=0)toi=fromi;i+;toi=0;(2)形参用字符指针变量形参用字符指针变量voidcopy_str(char*from,char*to)for(;*from!=0;from+,to+)*to=*from;*to=0;对上述函数体可有多种写法(1)while(*to=*from)!=0)to+;from+(2)while(*to+=*from+)!=0);(3)while(*from!=0)*to+=*from+;*to=0;(4)while(*to+=*from+);它

45、等价于它等价于while(*to+=*from+)!=0);(5)for(;(*to+=*from+)!=0;);或或(6)for(;*to+=*from+;);形参为数组时,也可以用指针变量形参为数组时,也可以用指针变量voidcopy_str(charfrom,charto)char*p1,*p2;p1=from;p2=to;while(*p2+=*p1+)!=0);形参和实参都可以是字符数组或字符指针变形参和实参都可以是字符数组或字符指针变量,很灵活量,很灵活3.对字符指针变量和字符数组的讨论(1)字符数组的每个元素存放一个字符,字符字符数组的每个元素存放一个字符,字符指针变量只存放字符

46、串的首地址,而不是指针变量只存放字符串的首地址,而不是将字符串放到字符指针变量中将字符串放到字符指针变量中(2)赋值方式,对字符数组只能对各元素赋初赋值方式,对字符数组只能对各元素赋初值,字符指针变量可以整体赋值值,字符指针变量可以整体赋值charstr20;str=”IloveChina”;/错误的错误的上述两语句不等价于:上述两语句不等价于:charstr20=”IloveChina”char*a;a=”IloveChina”;/合法的合法的上面两语句等价于:上面两语句等价于:char*a=”IloveChina”;(3)定义了字符数组后,编译时对数组分配单元,定义了字符数组后,编译时对数

47、组分配单元,而字符指针变量不分配单元,要人为赋初值而字符指针变量不分配单元,要人为赋初值(通常指向某一数组首址)(通常指向某一数组首址)char*s;scanf(“%s”,s);/语法上没有错误,但危险语法上没有错误,但危险通常的做法:通常的做法:char*s,str10;s=str;scanf(“%s”,s);(4)指针变量的值可以改变指针变量的值可以改变,而数组名是常量,不而数组名是常量,不可以改变其值可以改变其值char*a=”IloveChina”;a=a+7;printf(“%s”,a);结果是结果是China,字符指针变量输出字符串时从当前,字符指针变量输出字符串时从当前位置开始,

48、输出到位置开始,输出到0为止。为止。(5)定义了一个指针变量并使它指向一个字符串后,定义了一个指针变量并使它指向一个字符串后,就可以用下标形式引用其中的字符。就可以用下标形式引用其中的字符。char*a=”IloveChina”;ai10.5 指向函数的指针1.用函数指针变量调用函数用函数指针变量调用函数一个函数在编译时初分配一个入口地址,一个函数在编译时初分配一个入口地址,这个地址就称为这个地址就称为函数的指针函数的指针,可以用一个指,可以用一个指针变量指向函数,然后通过该指针变量调用针变量指向函数,然后通过该指针变量调用此函数。函数名代表该函数的入口地址此函数。函数名代表该函数的入口地址m

49、ain()intmax(int,int);int(*p)();/定义指向整型函数的指针定义指向整型函数的指针inta,b,c;p=max;scanf(%d%d,&a,&b);c=max(a,b);c=(*p)(a,b);/c=p(a,b);也可以也可以printf(max=%dn,c);(1)指向函数的指针变量的一般定义形式:指向函数的指针变量的一般定义形式:数据类型数据类型(*指针变量名)();指针变量名)();(2)函数调用可以通过函数名,也可以通过函数指针函数调用可以通过函数名,也可以通过函数指针调用调用(3)(*p)()只是定义了一个指向函数的指针变量,只是定义了一个指向函数的指针变量

50、,但指向哪一个并不确定;在一个程序中,但指向哪一个并不确定;在一个程序中,一个指一个指针变量可以先后指向返回类型相同的不同函数针变量可以先后指向返回类型相同的不同函数(4)给函数指针变量赋初值时,只给函数名不给参数给函数指针变量赋初值时,只给函数名不给参数(5)调用函数时,用(调用函数时,用(*p)取代函数名,实参照常)取代函数名,实参照常(6)对指向函数的指针变量进行加减运算没有意义,对指向函数的指针变量进行加减运算没有意义,如如p+2.用指向函数的指针作函数参数函数指针变量的函数指针变量的主要用途是做函数参数。主要用途是做函数参数。形参是指向函数的指针变量,实参是函数形参是指向函数的指针变

51、量,实参是函数名,结合的过程就是将函数的地址传给形名,结合的过程就是将函数的地址传给形参。通过用函数指针变量做函数形参,可参。通过用函数指针变量做函数形参,可以实现灵活调用不同的函数,提高函数的以实现灵活调用不同的函数,提高函数的通用性。通用性。例,设一个函数例,设一个函数process,在调用它的时,在调用它的时候,每次实现不同的功能。输入候,每次实现不同的功能。输入a,b后,第后,第一次调用时找出一次调用时找出a和和b中的大者,第二次找中的大者,第二次找出小者,第三次求出小者,第三次求a+b;main()intmax(int,int);intmin(int,int);intadd(int,

52、int);intprocess(int,int,int(*fun)();inta,b;scanf(%d%d,&a,&b);printf(max=);process(a,b,max);printf(min=);process(a,b,min);printf(add=);process(a,b,add);process(intx,inty,int(*fun)()intresult;result=(*fun)(x,y);printf(“%dn”,result);说说明明:主主函函数数中中对对max(),min(),add()等等三三个个函函数数的的声声明明是是必必不不可可少少的的,以以前前函函数数不

53、不声声明明,隐隐含含为为函函数数类类型型为为整整型型,但但在在此此max,min,add做做为为函函数数参参数数进进行行调调用用时时,只只给给函函数数名名而而没没有有函函数数的的实实参参及及括括号号,所所以以编编译译系系统统些些时时不不易易区区分分它它们们是是变变量量还还是是函函数数名名,以以前前做做为为函函数数调调用用时时,后后面面的的括括号号及及参参数数可可以以告告知知编编译译系系统统它它们们是是函函数数名名。 10.6 返回指针值的函数函数的类型为指针类型。函数的类型为指针类型。一般定义形式为:一般定义形式为:类型名类型名*函数名(参数列表)函数名(参数列表)int*a(intx,int

54、y)调调用用a后后能能得得到到一一个个指指向向整整型型数数据据的的指指针针。()的的优优先先级级高高于于*,所所以以这这是是函函数数形形式式,a前前的的*代代表表此此函函数数是是指指针针函函数数例,有若干名学生,例,有若干名学生,4门课,要求在用户输门课,要求在用户输入学生序号后,能输出该学生的全部成绩,入学生序号后,能输出该学生的全部成绩,用指针函数实现。用指针函数实现。定义函数定义函数search,返回第,返回第n个学生的首门课个学生的首门课的地址(列)的地址(列)float*search(float(*pointer)4,intn)float*pt;pt=*(pointer+n);ret

55、urnpt;main()floatscore4=60,70,80,90,56,89,67,88,34,78,90,6;float*search(float(*pointer)4,intn);float*p;intj,n;scanf(%d,&n);p=search(score,n);for(j=0;j4;j+)printf(%5.0f,*(p+j);printf(n);例,对上例中的学生,找出其中有不及格课例,对上例中的学生,找出其中有不及格课程的学生及其学号程的学生及其学号main()floatscore4=60,70,80,90,56,89,67,88,34,78,90,6;float*se

56、arch(float(*pointer)4);float*p;inti,j;for(i=0;i3;i+)p=search(score+i);if(p=*(score+i)printf(No.%dscores:,i);for(j=0;j4;j+)printf(%5.0f,*(p+j);printf(n);/end_if/end_forfloat*search(float(*pointer)4)inti;float*pt;pt=*(pointer+1);for(i=0;i4;i+)if(*(*pointer+i)60)pt=*pointer;returnpt;该函数的作用是检查一个学生是否有不及格

57、的该函数的作用是检查一个学生是否有不及格的课程,先让指针课程,先让指针pt指向下一个学生的第一门课,指向下一个学生的第一门课,如果该学生有不及格的课程,则让指针如果该学生有不及格的课程,则让指针pt指回指回该学生的每一门课,便于主函数进行判断。该学生的每一门课,便于主函数进行判断。10.7指针数组和指向指针的指针1.指针数组的概念指针数组的概念元素均为指针类型的数组,称为指针数组。元素均为指针类型的数组,称为指针数组。一般定义形式:一般定义形式:类型名类型名*数组名数组名数组长度数组长度;int*p4;的优先级高于的优先级高于*,所以,所以p先与先与结合,形结合,形成数组,然后再与成数组,然后

58、再与*结合,结合,*表示此数组是表示此数组是指针类型,每个元素都可指向一个整型变指针类型,每个元素都可指向一个整型变量量指针数组比较适合处理若干字符串,指针数组比较适合处理若干字符串,使字符串处理更加方便灵活。比如,使字符串处理更加方便灵活。比如,处理图书馆中的图书名字,由于书名处理图书馆中的图书名字,由于书名长度不同,所以用指针数组比较方便,长度不同,所以用指针数组比较方便,每个元素是个字符串指针。当要对字每个元素是个字符串指针。当要对字符串进行排序时,可以不改变字符串符串进行排序时,可以不改变字符串本身的存贮,只改变指针值即可,可本身的存贮,只改变指针值即可,可节约时间。节约时间。例,将若

59、干字符串按字母顺序(由小到大)输出例,将若干字符串按字母顺序(由小到大)输出voidsort(char*name,intn)char*temp;inti,j,k;for(i=0;in-1;i+)k=i;for(j=i+1;jn;j+)if(strcmp(namej,namek)0)k=j;if(k!=i)temp=namei;namei=namek;namek=temp;voidprint(char*name,intn)inti;for(i=0;in;i+)printf(%sn,namei);main()char*name=Followme,BASIC,Greatwall,FORTRAN,Co

60、mputerdesign;intn=5;sort(name,n);print(name,n);2.指向指针的指针指向指针数据的指针变量,简称为指向指针指向指针数据的指针变量,简称为指向指针的指针,定义的形式:的指针,定义的形式:类型类型*变量;变量;char*p;*运算的结合性从右向左,所以上述定义相当运算的结合性从右向左,所以上述定义相当于于char*(*p);*p是一个指向字符型的指针是一个指向字符型的指针变量,变量,*p是一个指向字符型指针变量的指是一个指向字符型指针变量的指针。针。例例1,用指向指针的指针输出字符串,用指向指针的指针输出字符串main()char*name=Follow

61、me,BASIC,Greatwall,FORTRAN,Computerdesign;char*p;inti;for(i=0;i5;i+)p=name+i;printf(%sn,*p);例例2,间接寻址举例,间接寻址举例main()staticinta5=1,3,5,7,9;int*num5=&a0,&a1,&a2,&a3,&a4;int*p;inti;p=num;for(i=0;i1)argv+;printf(%sn,*argv);argc-;命令行中给出命令行中给出file1ChinaBeijing则输出:则输出:ChinaBeijing也可以改写为:也可以改写为:main(intargc,

62、char*argv)while(argc-1)printf(%sn,*+argv);echo程序:程序:main(intargc,char*argv)while(argc-1)printf(%s%cn,*+argv,(argc1)?:n);在不同的参数间加一个空格,当所有参数输在不同的参数间加一个空格,当所有参数输出完毕,加一个回车符出完毕,加一个回车符10.8 小结1.有关指针的数据类型的小结有关指针的数据类型的小结intiint*pintanint*pnint(*p)nintf()int*p()int(*p)()int*p定定义义含含义义inti定定义义整型整型变变量量iint*pP为为指

63、向整型数据的指指向整型数据的指针变针变量量intan定定义义整型数整型数组组aint*pn定定义义指指针针数数组组p,每个分量是一个指,每个分量是一个指针变针变量量int(*p)np为为指向一指向一维维数数组组的指的指针针intf()整型函数整型函数int*p()p为为函数,它的返回函数,它的返回值值是指向整型是指向整型变变量的指量的指针针int(*p)()p为为指向整型函数的指指向整型函数的指针针int*pp是一个指是一个指针变针变量,它指向一个指向整型数据量,它指向一个指向整型数据的指的指针变针变量量2.指针运算小结(1)指针变量加(减)一个整数指针变量加(减)一个整数n:加:加n个存贮单

64、元个存贮单元的地址的地址(2)指针变量赋值指针变量赋值p=&a;/将变量的地址赋给指针变量将变量的地址赋给指针变量p=array;/将数组的首地址赋给指针变量将数组的首地址赋给指针变量p=&arrayi;p=max;/函数的入口地址赋给函数的入口地址赋给pp1=p2;/让让p1指向指向p2所指向的存贮单元所指向的存贮单元p=NULL;/p不指向任何存贮单元,但它已被赋初不指向任何存贮单元,但它已被赋初值,可以避免无初值对系统造成的破坏值,可以避免无初值对系统造成的破坏(3)两个指针变量可以相减:如果两个指针两个指针变量可以相减:如果两个指针变量指向同一个数组的元素,两指针变变量指向同一个数组的元素,两指针变量之差是两个指针之间的元素个数;两量之差是两个指针之间的元素个数;两个指针相加没有意义个指针相加没有意义(4)若两个指针指向同一个数组的元素,则可若两个指针指向同一个数组的元素,则可以进行比较。指向前面的元素的指针变量以进行比较。指向前面的元素的指针变量“小于小于”指向后面元素的指针变量。否则指向后面元素的指针变量。否则无意义无意义3. void指针类型 void代表一种抽象的数据类型,使用时代表一种抽象的数据类型,使用时进行强制类型转换。进行强制类型转换。void*p2;char*p1;p1=(char*)p2;

展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 大杂烩/其它

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号