《(本科)第9章 指针ppt课件.pptx》由会员分享,可在线阅读,更多相关《(本科)第9章 指针ppt课件.pptx(46页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、课程主讲人:第9章 指针2 第 9章 指针C语言程序设计第9章 指针计算机教研室3 第 9章 指针9.1 指针的概念n程序运行时,数据和程序代码都将被传输至计算机的内存。内存是计算机用于存储数据的存储器,最小单元为1字节(Byte)。为了能够正确地访问内存,为每一个内存单元编号,这个编号就是对应单元的地址。n当定义一个变量时,编译时系统根据变量类型自动分配相应长度的内存空间。变量占用内存单元的数量取决于编译环境,大多数编译环境中,除了整型变量以外,其他类型变量占用内存单元是不变的。9.1.1 地址4 第 9章 指针9.1 指针的概念nVisual C+6.0中,整型变量占用4个字节,单精度型变
2、量占用4个字节,字符变量占用1个字节。n假设有以下变量:nint a=3;nfloat b=4.18;nchar ch=M;n则变量a,b,ch占用内存单元的情况示例 如图9-1所示。9.1.1 地址5 第 9章 指针9.1 指针的概念n用一个变量来保存内存单元的地址,这个变量就被称为指针变量。n根据内存单元中存放的数据类型,指针变量也分为不同的类型。n严格地说,指针和指针变量是不同的。一个指针的值是一个地址,属于常量,而一个指针变量是存放地址的变量,它的值是变化的,可以是不同的地址,属于变量。9.1.2 指针变量的定义6 第 9章 指针9.1 指针的概念n在使用指针变量之前,必须先定义,定义
3、指针变量的一般形式如下:n存储类型 数据类型名 *指针变量名=初始值;存储类型为变量本身的存储类型,变量的存储类型在第2章中已经介绍,在此就不再赘述了。数据类型是指针变量指向的内存单元所存放数据的数据类型,即指针变量指向变量的数据类型。*表示定义的是一个指针变量,指针变量名的命名与一般变量相同,需遵守标识符的命名规则。初始值通常为某个变量的地址或为NULL。9.1.2 指针变量的定义7 第 9章 指针9.1 指针的概念n指针变量定义示例如下: int a,*p1=&a;/*p1是指向整型变量的指针,p1指向了变量a的地址,&是取地址运算符。*/float *p2;/*p2是指向单精度浮点型变量
4、的指针,没有赋初值*/char *p3=NULL;/*p3是指向字符变量的指针,p3指向了一个空地址*/注意:指针变量的值是指针指向变量在内存单元中的首地址。9.1.2 指针变量的定义8 第 9章 指针9.1 指针的概念n定义了指针变量之后,必须赋值后才能使用。n赋值方式有如下两种: (1)定义时赋初值方式在定义指针变量的同时,直接将变量的地址赋值给指针变量:char ch,*p=&ch;(2)普通赋值方式普通赋值方式是指,定义指针变量之后,将变量的地址赋值给指针变量:char ch,*p;p=&ch;注意:指针变量的值是指针指向变量在内存单元中的首地址。9.1.3 指针变量的使用9 第 9章
5、 指针9.1 指针的概念n注意:给指针变量赋值是指将普通变量的地址赋值给指针变量,也就是说指针变量指向了普通变量。也可以将空值赋值给指针变量,如下:char *p=NULL;表示指针变量p不指向任何内存单元。9.1.3 指针变量的使用10 第 9章 指针9.1 指针的概念n当给指针变量赋值后,就可以使用指针变量了,使用的方式有如下两种:(1)取变量的值*指针变量名表示指针变量所指向变量的值。(2)取变量的地址指针变量名表示所指向变量的地址。例如:char ch,*p;p=&ch;*p=M;9.1.3 指针变量的使用ch、*p的值均为M,&ch、p均表示变量ch的地址。11 第 9章 指针9.1
6、 指针的概念【例9.1】通过指针变量访问整型变量。#include void main() int a,b,*p1,*p2; p1=&a; p2=&b; a=66; *p2=88; printf(a=%d,b=%dn,a,b); printf(a=%d,b=%dn,*p1,*p2); 9.1.3 指针变量的使用n 第2,3行分别将指针变量p1和p2指向变量a和b。n 需要注意的是,第5行将88赋值给*p2,等价于b=88,*p2表示的是变量b的值,而p2表示变量b的地址即&b,这里一定不能写成p2=88。n 最后输出时*p1和*p2分别表示变量a和变量b的值,因此最后两行printf函数的作用
7、是相同的。12 第 9章 指针9.1 指针的概念#include void main() int *p1,*p2,*p,a,b;printf(请输入两个整数:n);scanf(%d%d,&a,&b);p1=&a;p2=&b;9.1.3 指针变量的使用if(ab)p=p1;p1=p2;p2=p;printf(a=%d,b=%dn,a,b);printf(min=%d,max=%dn,*p1,*p2); 【例9.2】将输入的两个整数按由小到大的顺序输出。13 第 9章 指针9.2 指针的基本运算n指针算术运算的功能是完成指针的移动,来实现对不同内存单元中数据的访问。n对不同的指针变量类型,移动的单
8、位长度有所不同。n指针的算术运算有加(+)、减(-)、自增(+)、自减(-)4种。n一个指针加、减一个常量n后的新位置,是在原来基础上加或减“sizeof(指针数据类型)*n”,而不是指针直接加、减n。9.2.1 指针的算术运算14 第 9章 指针9.2 指针的基本运算9.2.1 指针的算术运算15 第 9章 指针9.2 指针的基本运算#include void main()int a=5,*p1=&a;char ch=M,*p2=&ch;double b=3.14,*p3=&b;printf(1.整型指针变量p1的变化:n);printf(变量a的值tt变量a的地址:n);printf(*p
9、1=%dttp1=%lun,*p1,p1);printf(变量a下一单元的值tt变量a下一单元的地址:n);printf(*(p1+1)=%dttp1+1=%lun,*(p1+1),p1+1);printf(2.字符型指针变量p2的变化:n);printf(变量ch的值tt变量ch的地址:n);printf(*p2=%cttp2=%lun,*p2,p2);9.2.1 指针的算术运算printf(变量ch下一单元的值tt变量ch下一单元的地址:n);printf(*(p2+1)=%cttp2+1=%lun,*(p2+1),p2+1);printf(3.双精度型指针变量p3的变化:n);print
10、f(变量b的值tt变量b的地址:n);printf(*p3=%fttp3=%lun,*p3,p3);printf(变量b下一单元的值tt变量b下一单元的地址:n);printf(*(p3+1)=%fttp3+1=%lun,*(p3+1),p3+1);【例9.3】阅读下面的程序,了解指针移动时指针变量值的变化情况。16 第 9章 指针9.2 指针的基本运算n两个指针在有意义的情况可以做比较运算。n一般常用于比较两个指针是否相等,即两个指针是否指向同一个变量。假设有:int a,*p1,*p2=&a;则表达式p1=p2的值为0(假)。如果再加一条语句,p1=&a;那么表达式p1=p2的值就为1(真
11、)。9.2.2 指针的关系运算17 第 9章 指针9.2 指针的基本运算#include Void main()int a,b,*p1=&a,*p2=&b; printf(p1=p2) is %dn,p1=p2); p2=&a; printf(p1=p2) is %dn,p1=p2);9.2.2 指针的关系运算【例9.3】阅读下面的程序,了解指针的关系运算。【运行结果】(p1=p2) is 0(p1=p2) is 118 第 9章 指针9.3 指向数组的指针变量n每个变量在内存单元中都有自己的地址,一个数组包含多个数组元素,这些数组元素在内存中是连续存放的,每个数组元素也有各自相应的地址,数组
12、名代表数组的首地址,也就是数组中第一个元素的地址,当定义数组时,其首地址就固定不变了。n指针变量可以指向普通变量,也可以指向数组中的元素。通过指针变量来指向数组中的不同元素,可以使程序的效率更高,执行速度更快。19 第 9章 指针9.3 指向数组的指针变量n定义指向一维数组的指针变量的方法如下:int a3,*p;/*定义一个整型数组a和一个整型指针变量。*/p=a; /*指针p指向数组a的首地址。*/n假定数组a的首地址为500,指针p与数组a的存储关系如图9-3所示。9.3.1 指向一维数组的指针变量20 第 9章 指针9.3 指向数组的指针变量n假定现在指针p指向数组a的首地址,指针p与
13、数组a的关系如表9-1所示。9.3.1 指向一维数组的指针变量说明地址表示说明数组元素表示a的首地址a、p、&a0a0的值*a、*p、a0a1的地址a+1、p+1、&a1a1的值*(a+1)、*(p+1)、a1、p1ai的地址a+i、p+i、&aiai的值*(a+i)、*(p+i)、ai、pi表9-1 指针p与数组a的关系21 第 9章 指针9.3 指向数组的指针变量9.3.1 指向一维数组的指针变量【例9.5】假设有一个整型数组a,输入数组元素后,通过不同的方法输出各元素的值。#include void main() int i,a10,*p; printf(请输入数组元素的值(10个整数)
14、:n); for(i=0;i10;i+) scanf(%d,&ai); printf(“利用下标法输出数组元素的值:n); for(i=0;i10;i+) printf(%d ,ai);printf(n通过数组名计算数组元素地址,输出数组元素的值:n);for(i=0;i10;i+) printf(%d ,*(a+i);printf(n用指针变量指向数组元素,输出数组元素的值:n);for(p=a;p(a+10);p+) printf(%d ,*p);22 第 9章 指针9.3 指向数组的指针变量n定义指向二维数组的指针变量的方法如下: int a34,*p=a0;对于数组 a,它可以分解成三
15、个一维数组,即 a0、a1、a2。每一个一维数组又包含了 4 个元素,例如 a0 包含 a00、a01、a02、a03。a、a0和指针p都指向了数组a的首地址,这里要注意的是,a虽然也指向了数组的首地址,但是它是一个行指针,代表的是第0行的首地址,因此a+1代表第1行的首地址。9.3.2 指向多维数组的指针变量23 第 9章 指针9.3 指向数组的指针变量n给指针变量p赋初值的形式有如下两种:np=a0;n或p=&a00;n而p=a是不对的,编译时会有警告产生。n指针变量p与二维数组a在内存中的存储关系如图9-5所示。9.3.2 指向多维数组的指针变量24 第 9章 指针9.3 指向数组的指针
16、变量n假定现在p=a0;,即指针p指向数组a的首地址500,指针p与数组a的关系如表9-2所示。9.3.2 指向多维数组的指针变量说明地址表示说明数组元素表示a的首地址a、p、*a、a0、&a00a00的值*a、*p、*a0、a00a01的地址p+1、*a+1、a0+1、&a00+1a01的值*(p+1)、*(*a+1)、*(a0+1)、a01a10的地址a+1a10的值*(a+1)、*(p+4)、*a1、a10ai0的地址a+iai0的值*(a+i)、*(p+i*4)、*ai、ai0aij的地址p+i*4+j、*a+i*4+j、a0+i*4+j、&a00+i*4+j、&aijaij的值*(p
17、+i*4+j)、*(*a+i*4+j)、*(a0+i*4+j)、*(&a00+i*4+j)、aij表9-2 指针p与数组a的关系25 第 9章 指针9.3 指向数组的指针变量#include void main() int a34=1,2,3,4,5,6,7,8,9,10,11,12; int *p; p=a0; printf(1:输出数组a的首地址:n); printf(a=%lun,a); printf(*a=%lun,a); printf(p=%lun,p); printf(a0=%lun,a0); printf(&a00=%lun,&a00); printf(2:输出数组a第1行的首地
18、址:n); printf(a+1=%lun,a+1);9.3.2 指向多维数组的指针变量printf(3:输出数组元素a01的地址:n);printf(*a+1=%lun,*a+1);printf(p+1=%lun,p+1);printf(a0+1=%lun,a0+1);printf(&a00+1=%lun,&a00+1);printf(4:输出数组元素a12的地址:n);printf(*a+1*4+2=%lun,*a+1*4+2);printf(p+1*4+2=%lun,p+1*4+2);printf(a0+1*4+2=%lun,a0+1*4+2);printf(&a00+1*4+2=%lu
19、n,&a00+1*4+2);【例9.6】阅读程序,理解指针与二维数组地址的关系。26 第 9章 指针9.3 指向数组的指针变量#include void main() int a34=1,2,3,4,5,6,7,8,9,10,11,12; int *p,i,j; p=a0; printf(数组中的数据如下:n); for(i=0;i3;i+) for(j=0;j4;j+) printf(a%d%d=%d ,i,j,aij); printf(n); printf(第0行第0列元素的值:n); printf(*a=%dn,*a);9.3.2 指向多维数组的指针变量printf(*p=%dn,*p)
20、;printf(*a0=%dn,*a0);printf(a00=%dn,a00);printf(第0行第1列元素的值:n);printf(*(*a+1)=%dn,*(*a+1);printf(*(p+1)=%dn,*(p+1);printf(*(a0+1)=%dn,*(a0+1);printf(a01=%dn,a01);printf(第1行第2列元素的值:n);printf(*(*a+1*4+2)=%dn,*(*a+1*4+2);printf(*(p+1*4+2)=%dn,*(p+1*4+2);printf(“*(a0+1*4+2)=%dn”,*(a0+1*4+2);【例9.6】阅读程序,理解
21、指针与数组元素的关系。printf(a12=%dn,a12);27 第 9章 指针9.4 指向字符串的指针变量n在C语言中,字符串的表示形式有如下两种:1.用字符数组表示一个字符串。2.用字符指针指向一个字符串。28 第 9章 指针9.4 指向字符串的指针变量1.用字符数组表示一个字符串#include void main() char str=Hello World!; printf(字符串为:n); printf(%sn,str);【例9.8】定义一个字符数组,初始化后,输出该字符串的内容。29 第 9章 指针9.4 指向字符串的指针变量n利用指向字符型变量的指针,可以定义一个字符串,形式
22、如下:char *p=”Hello World!”;n字符串p在内存单元中的存储情况如图9-6所示。n要引用字符串中的某个字符,可以有以下两种形式:*(p+i) pi2. 用字符指针指向一个字符串30 第 9章 指针9.4 指向字符串的指针变量#include void main() char *p=Hello World!; printf(字符串为:n); printf(%sn,p);【例9.9】利用指向字符型变量的指针,定义一个字符串,输出该字符串的内容。2. 用字符指针指向一个字符串31 第 9章 指针9.4 指向字符串的指针变量#include void main() char str
23、20=Hello World!,*p=str; int i; printf(通过指针输出数组元素:n); printf(1.整体输出:n%sn,p); printf(2.单个输出:n); while(*p!=0) putchar(*p); 【例9.10】利用指针来输出字符数组中的元素。2. 用字符指针指向一个字符串 p+; p=str; printf(n3.单个输出:n); for(i=0; pi!=0;i+) printf(%c,pi);32 第 9章 指针9.5 指针变量作为函数的参数n函数的参数不仅可以是整型、字符型、浮点型等数据类型,还可以是指针类型变量。n当指针变量作为函数参数时,函
24、数之间传递的就是变量的地址,也就是说,函数中形参值改变的同时,实参值同步改变了。33 第 9章 指针9.5 指针变量作为函数的参数#include void swap(int *pl,int *p2) int t; t=*pl; *pl=*p2; *p2=t;【例9.11】将输入的两个整数按由小到大的顺序输出,要求利用函数进行交换,函数参数为指针类型数据。void main() int a,b; int *pointer1,*pointer2; printf(请输入两个整数:n); scanf(%d%d,&a,&b); pointer1=&a; pointer2=&b; if(ab) swap
25、(pointer1,pointer2); printf(a=%d,b=%dn,a,b); printf(min=%d,max=%dn,*pointer1,*pointer2);34 第 9章 指针9.5 指针变量作为函数的参数【程序说明】在主函数中输入两个整数a和b(88和66),指针变量pointer1指向变量a,指针变量pointer2指向变量b,如图9-7(a)所示。然后比较a、b的大小,如果ab就调用函数swap。swap函数是用户定义的子函数,它的作用是交换变量a和b的值。注意:实参是指针变量pointer1和pointer2,形参是指针变量p1和偏p2。函数调用时,pointer1
26、、pointer2分别把变量a、b的地址传给形参变量p1和p2,这种方式为“传址”。此时,pointer1、p1共同指向了变量a,pointer2、p2共同指向了变量b,如图9-7(b)所示。在函数swap中,完成*p1、*p2的交换,即变量a、b的交换,如图9-7(c)所示。函数调用结束后,形参p1、p2被释放,指针及变量情况如图9-7(d)所示。35 第 9章 指针9.5 指针变量作为函数的参数36 第 9章 指针9.6 指针与函数n函数类型是指函数返回值的类型。当函数的返回值是一个指针(即地址值)的时候,该函数就被称为指针型函数。n定义指针型函数的形式为:数据类型名 *函数名(函数参数列
27、表);说明:数据类型是指函数返回的指针指向的数据类型。*表示此函数为指针型函数,其函数值为指针,返回值是一个指针(即地址的值)。(函数参数列表)中的括号为函数调用运算符,在调用语句中,即使函数不带参数,其参数表的一对括号也不能省略。例如:int *a(int x,int y);9.6.1 指针型函数37 第 9章 指针9.6 指针与函数9.6.1 指针型函数#include int *search(int (*sp)3,int n) int *p1; p1=*(sp+n); return(p1);【例9.12】有若干学生的成绩,每个学生有3门课程,在用户输入学生序号时,输出该学生的全部成绩,要
28、求用指针函数实现。void main() int score 3=99,98,97,88,87,86,98,88,86,60,50,40; int i,s,*p; printf(请输入要查找成绩的学生序号:n); scanf(%d,&s); printf(第%d个学生的成绩为:n,s); p=search(score,s); for(i=0;i3;i+) printf(%dt,*(p+i);38 第 9章 指针9.6 指针与函数9.6.1 指针型函数【程序说明】在主函数中定义一个二维数组存放学生的成绩,输入要查找成绩学生序号s,注意学生序号从0开始,然后调用search函数,来查找序号为s学生
29、成绩存放的地址。主函数调用search函数,将score数组首行地址传给形参sp,注意的是,score是一个行指针。search函数为指针型函数,形参sp是指向一维数组的指针变量,sp+1指向了第1行第0列元素,是一个行指针,加了*之后,就变成指向列的指针了。调用search函数后,得到一个地址(指向第s个学生第0门课的成绩),赋值给指针变量p。然后将该学生3门课的成绩输出,*(p+i)表示该学生第i门课的成绩。39 第 9章 指针9.6 指针与函数n每个函数在内存单元中都占用一定的存储空间,都有自己执行时的入口地址。定义一种指针变量,用来存放函数的入口地址,这种指向函数的指针变量被称为函数指
30、针变量,简称函数指针。n定义函数指针变量的形式为:数据类型名 *函数名(函数参数列表);数据类型名 (*指针变量名)( );说明:数据类型是指函数返回值的数据类型。(*指针变量名)*表示定义的是一个指针变量。( )表示指针变量指向的是一个函数。例如:int (*p)( );9.6.2 指向函数的指针注意:int (*p)( )和int *p( )的区别如下:int (*p)( )表示定义了一个指向函数入口地址的指针变量p,这两对括号都不能少。int *p()表示定义了一个指针型的函数p,该函数的返回值为整型。40 第 9章 指针9.6 指针与函数9.6.2 指向函数的指针#include in
31、t max(int x,int y) int z; if(xy) z=x; else z=y; return(z);【例9.13】从键盘中输入两个整数,并找出其中的大数。void main() int a,b,c; printf(请输入两个整数:n); scanf(%d%d,&a,&b); c=max(a,b); printf(a=%d,b=%d,max=%dn,a,b,c);41 第 9章 指针9.6 指针与函数9.6.2 指向函数的指针#include int max(int x,int y) int z; if(xy) z=x; else z=y; return(z);【例9.14】从键
32、盘中输入两个整数,并找出其中的大数。利用指针变量来访问max函数。void main() int a,b,c; int (*p)(int,int); p=max; printf(请输入两个整数:n); scanf(%d%d,&a,&b); c=(*p)(a,b); printf(a=%d,b=%d,max=%dn,a,b,c);42 第 9章 指针9.6 指针与函数9.6.2 指向函数的指针【程序说明】在主函数中第2行定义了一个指针函数的指针变量p,该函数的返回值为整型,有两个参数均为整型。注意,这里一定不能写成int *p(int,int);,后者表示定义了一个返回值为指针的函数。在主函数第
33、3行中,p=max;表示把函数max的入口地址赋值给指针变量p。函数名代表了函数的入口地址。调用*p就相当于调用max函数。主函数第6行中,c=(*p)(a,b);调用了max函数,并将函数的返回值赋值给了变量c。43 第 9章 指针9.7 指针数组n在数组中,如果每一个数组元素均为指针型数据,这些指针都指向相同的数据类型,这种数组称为指针数组。n指针数组的定义形式如下:存储类型 数据类型名 *数组名元素个数;说明:存储类型为数组本身的存储类型,与变量的存储类型相同,变量的存储类型在第2章中已经介绍,这里就不再介绍了。数据类型是指数组元素指针所指向的数据类型。*数组名表示数组类型是指针数组,其
34、中的元素均为指针。例如:int *p5;44 第 9章 指针9.7 指针数组#include void main() static int score43=99,98,97,88,87,86,98,88,86,60,50,40; int *p4=score0,score1,score2,score3; int i,j; for(i=0;i4;i+) printf(“第 %d个学生的成绩如下:n,i); for(j=0;j3;j+) printf(%dt,pij); printf(n); 【例9.15】有若干学生的成绩,每个学生有3门课程,要求用指针数组输出所有学生的成绩。【程序说明】程序中第2
35、行定义了一个指针数组p,该数组中有4个元素,每个元素都是一个指针,分别指向了数组score中的score0、score1、score2和score3,也就是指向了score数组每一行的首地址。程序中用pij访问数组元素scoreij。45 第 9章 指针9.7 指针数组#include #include void sort(char *string ,int n)char *temp; int i,j,k; for(i=0;in-1;i+) k=i; for(j=i+1;j0) k=j; if(k!=i) temp=stringi;stringi=stringk;stringk=temp;【例9.16】将若干字符串按字母顺序输出显示。void print(char *string ,int n) int i; for(i=0;ik(即i),如果strcmp(stringk,stringj)0,即前面字符串后面字符串,那么交换stringi和stringj的值,stringi和stringj表示各自指向字符串的地址,也就是让stringi指向了stringj原来指向的字符串,stringj指向了stringi原来指向的字符串。print函数中,string0到string4分别表示各字符串(按从小到大排好序的字符串)的首地址。
限制150内