8指针及其应用
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
提示:注意区分变量的地址和变量的值这两个概念。
下一页
返 回
8.1 指针的基本用法
存储单元地址惟一地对应着(或指向)存储单元,因此C语言将存储 单元地址形象地称为"指针"。 前面学习的变量,都是用来存放基本类型数据的,如存放整数或实数 等,这些变量称为简单变量。在C语言中,还可以定义一种特殊的变 量,这种变量专门用来存放另一个变量的地址(即指针),称为指针 变量。 如果p是指针变量,而且p中存放着变量a的地址,则称p指向a,常用 图8-1所示的形式表示。那么可以通过指针变量p引用它所指向的变量 a,这种变量访问方式称为变量的间接访问。 本章主要介绍的内容就是变量的间接访问。
第8章 指针及其应用
第8章指针及其应用
学习目标
掌握指针的概念及基本操作,指针在数组和函数中的应用。
学习内容
指针、指针变量的概念,指针变量定义及使用,指针与一维数组, 指针与二维数组,指针与字符串,指针与函数。
下一页
返 回
第8章 指针及其应用
8.1 指针的基本用法 8.2 指针与数组 8.3 指针与函数 8.4 指针应用实例 8.5 本章小结 8.6 实训
8.1 指针的基本用法
程序运行结果:
【例8-2】从键盘上输入任意三个实数,利用指针的方法将这三个实 数按大小进行排序。 【编程思路】 (1)输入3个实数分别放到变量a、b、c中。 (2)3个指针变量p1、p2、p3分别指向变量a、b、c。 (3)比较变量的值,最终使p1指向最大值,p3指向最小值。 (4)按顺序输出p1、p2、p3所指向的变量的值。
8.2 指针与数组
printf("%5d",*p1);
printf("\n"); } 程序运行结果为:
上一页
下一页
返 回
8.2 指针与数组
8.2.2 指针与二维数组
1. 二维数组元素的地址 例如:int a[3][3]; 与一维数组名一样,二维数组名a也是数组的首地址。但是二者不同 的是,二维数组名的基类型不是数组元素类型,而是一维数组类型, 因此二维数组名a是一个行指针,其指向如图8-4所示。 二维数组a包含三个行元素:a[0]、a[1]和a[2],而它们又都是一维数 组名,因此也是地址常量,但是它们的基类型与数组元素类型一致。 第0行首地址:a[0] 第1行首地址:a[1] 第2行首地址:a[2]
8.1 指针的基本用法
{p=p1;p1=p3;p3=p;} if(b<c) {p=p2;p2=p3;p3=p;} printf("%.2f,%.2f,%.2f\n",*p1,*p2,*p3); } 程序运行结果:
该程序执行过程中,变量a、b、c的值始终未变,只是使指针p1最终 指向值最大的变量,使指针p3最终指向值最小的变量。 上一页 返 回
上一页
下一页
返 回
8.1 指针的基本用法
8.1.2 指针变量的定义和使用
1. 指针变量的定义 任何变量在使用前都必须定义,指针变量也一样。指针变量的一般定 义形式为: 基类型名 *指针变量名; 例如:int *p1,*p2; 说明: (1)定义了两个指针变量,变量名为p1和p2,这两个变量只能用来 存放地址。 (2)*是一个说明符用来说明定义的是指针变量,定义指针变量时必 须有。 (3)基类型表示指针变量所指向的变量的类型,也就是说,p1、p2 中只能存放整型变量的地址。 上一页 下一页 返 回
8.1 指针的基本用法
2. 指针变量的使用 (1)运算符“&”和“*” 运算符“&”为取地址运算符,后跟一个变量,表示取变量的地址。 比如,&a表示变量a的地址。 运算符“*”为间接访问运算符,后跟一个指针变量,表示取这个指 针变量所指向的变量的值。 (2)指针变量的赋值 通过给指针变量赋地址值,可以让指针变量指向某个变量。例如有以 下定义和语句: int a,b,*pa,*pb; pa=&a; /*指针变量pa指向变量a */ pb=&b; /*指针变量pb指向变量b*/ 上一页 下一页 返 回
上一页
下一页
返 回
8.1 指针的基本用法
【例8-1】通过指针变量访问整型变量。 【程序代码】 #include <stdio.h> void main( ) { int i,j,*pi; /*定义整型变量i和j,指针变量pi*/ i=10; pi=&i; /*使指针变量p指向变量i*/ j=*pi+5; /*通过指针变量访问变量i,等价于j=i+5;*/ printf("%d\n",i); printf("%d,%d\n",*pi,j); } 上一页 下一页 返 回
8.2 指针与数组
3. 数组元素的引用 针对数组元素地址的不同表示形式,数组元素的引用形式也有多种, 见表8-2。 下面语句通过数组名逐个输出数组a中各元素的值: for(i=0;i<10;i++) printf("%5d",*(a+i)); 这里首地址a始终指向数组元素a[0],并没有移动,通过变量i值的变 化来引用到每个元素。 下面语句通过移动指针来逐个输出数组a中各元素的值: for(p=a;p<a+10;p++) printf("%5d",*p);
上一页
下一页
返 回
8.2 指针与数组
所以a[0]+1就是数组元素a[0][1]的地址,a[1]+1是数组元素a[1][1]的地 址,那么任意的数组元素a[i][j]的地址是a[i]+j。 二维数组元素的地址表示形式较多,每种地址形式都有对应的数组元 素引用方法。比如: 数组元素地址:① &a[i][j] ② a[i]+j ③ *(a+i)+j 数组元素引用:① a[i][j] ② *(a[i]+j) ③ *(*(a+i)+j) 2. 指向二维数组元素的指针变量(列指针) 例如:int a[3][2],*p; p=&a[0][0]; 二维数组在内存中是按行顺序存储的,因此,可以通过对指向数组元 素的指针变量进行加减运算来达到引用任意数组元素的目的,引用方 法与引用一维数组元素一样。 上一页 下一页 返 回
8.2 指针与数组
8.2.1 指针与一维数组
1. 指针的移动 当指针变量指向一串连续的存储单元(即数组)时,可以对指针变量 加上或减去一个整数来进行指针的移动和定位。例如有如下语句: int a[5]={10,20,30,40,50},*p,*q; p=&a[0]; 指针p的指向情况如图8-2(a)所示。在此基础上,随着下面各个语句的 执行,指针p和q的指向会发生相应变化。 q=p+1; 如图8-2(a)所示,使指针变量q指向数组元素a[1] q++; 指针后移,指针变量q指向数组元素a[2] q+=2; 指针变量q指向数组元素a[4]
上一页
下一页
返 回
8.1 指针的基本用法
【程序代码】 #include <stdio.h> void main( ) { float a,b,c,*p1,*p2,*p3,*p; printf("请输入3个实数:"); scanf("%f,%f,%f",&a,&b,&c); p1=&a; p2=&b; p3=&c; if(a<b) {p=p1;p1=p2;p2=p;} if(a<c) 上一页 下一页 返 回
上一页
下一页
返 回
8.2 指针与数组
【例8-4】使数组中的元素逆序存放(不借助其它数组),要求用指 针的方法处理。 【编程思路】 (1)定义两个指针变量p1、p2,使p1指向第一个元素、p2指向最后 一个元素。 (2)将p1、p2所指向的数组元素的值互换,然后使p1指向第二个元 素、p2指向倒数第二个元素,再做上面的互换操作,这样重复下去, 直到p1指向了p2的后面或p1和p2指向了同一元素为止。 【程序代码】 #include <stdio.h> void main( ) { 上一页 下一页 返 回
下一页
返 回
8.2 指针与数组
q--; 指针变量q指向数组元素a[3] p++; 指针变量p和q的指向如图8-2 (b) 所示 现在如果有语句 i=*p;j=*q; 则i中的值为20,j中的值为40。若有语句 k=q-p; 则k中的值为2。表达式p<q的值为真,因为当前指针变量p中 存的地址值小于指针变量q中存的地址值。 2. 数组元素的地址 C程序中,数组名是数组的首地址,即第1个数组元素的地址,该地 址是地址常量,因此不能被修改或重新赋值,例如,对数组名a来说, a++; 或a=&a[2]; 都是错误的使用方法。 虽然不能对数组名进行赋值,但可以通过数组名来表示数组元素的地 址,从而也能达到引用数组元素的目的。 例如:int a[10],*p;p=a; 此时指针p指向数组a的第1个元素,如图8-3 所示。数组元素地址的几种表示形式见表8-1。 上一页 下一页 返 回
上一页
下一页
返 回
8.1 指针的基本用法
j=*p+1; /*取指针变量p所指向的存储单元中的值加1后赋给变量j,j的 值为11*/ *p=*p+1; /*取指针变量p所指向的存储单元中的值,加1后再放入p所 指向的存储单元中,也就是使变量i的值增1变为11*/
小测验 int a=11,b=22,*pa,*pb; pa=&a; pb=&b; 在上面程序段的基础上,执行语句pa=pb;和执行语句*pa=*pb;有什么不同?
8.2 指针与数组
int a[10],*p1,*p2,temp; printf("请输入10个数:"); for(p1=a;p1<a+10;p1++) /*输入一个整数,存放在p1所指的存 储单元中*/ scanf("%d",p1); for(p1=a,p2=a+9;p1<p2;p1++,p2--) /*通过交换首尾对应位置上 的值实现逆置*/ { temp=*p1; *p1=*p2;*p2=temp; /*两个指针变量所指向 的元素的值互换*/ } printf("逆序后数组的值: "); for(p1=a;p1<a+10;p1++) 上一页 下一页 返 回
上一页
返 回
பைடு நூலகம்
8.1 指针的基本用法
8.1.1 指针的概念
计算机的内存是以字节为单位的一片连续的存储空间,每个字节都有 一个编号,这个编号称为内存单元地址。这就如同旅馆的每个房间都 有一个房间号一样,如果没有房间号,旅馆的工作人员就无法进行管 理,同样没有字节编号,系统就无法对内存单元进行管理。 若在程序中定义了一个变量,系统就会根据变量的类型为变量在内存 中分配若干字节的存储空间,此后这个变量的单元地址也就确定了。 有了变量的地址,就可以立即找到该变量所在的存储单元并进行数据 的存取操作。这种通过变量地址存取变量值的方式称为变量的直接访 问。 程序中通常是通过变量名对变量进行访问,因为变量名是变量的符号 地址,它与单元物理地址之间的联系由系统自动建立。
上一页
下一页
返 回
8.2 指针与数组
float score[10],*p,sum=0,ave; printf("请输入10个学生成绩:"); for(p=score;p<score+10;p++) scanf("%f",p); for(p=score;p<score+10;p++) sum+=*p; /*取各成绩累加到sum 中*/ ave=sum/10; /*求平均成绩*/ printf("平均成绩=%.2f\n",ave); } 程序运行结果:
上一页
下一页
返 回
8.2 指针与数组
此语句在执行过程中,指针p首先指向元素a[0],输出操作输出的是第 一个元素的值,执行了p++后,指针指向了元素a[1],此时再做输出 操作,输出的是第二个元素的值,依次下去,指针会逐个指向每个元 素,再输出它们的值。当指针p指向最后一个元素后面的存储单元时, 循环结束。 【例8-3】有一个数组score ,存放10个学生的成绩,求平均成绩,要求 通过指针变量来访问数组元素。 【程序代码】 #include <stdio.h> void main( ) {
8.1 指针的基本用法
下面的定义和语句是错误的: float x; int *p; p=&x; 错误原因是x的类型和p的基类型不一致。 (3)通过指针变量引用变量 例如,有以下定义和语句: int i,j,*p; p=&i; *p=10; /*将10赋给p所指向的变量即变量i,等价于赋值语句i=10;*/
下一页
返 回
8.1 指针的基本用法
存储单元地址惟一地对应着(或指向)存储单元,因此C语言将存储 单元地址形象地称为"指针"。 前面学习的变量,都是用来存放基本类型数据的,如存放整数或实数 等,这些变量称为简单变量。在C语言中,还可以定义一种特殊的变 量,这种变量专门用来存放另一个变量的地址(即指针),称为指针 变量。 如果p是指针变量,而且p中存放着变量a的地址,则称p指向a,常用 图8-1所示的形式表示。那么可以通过指针变量p引用它所指向的变量 a,这种变量访问方式称为变量的间接访问。 本章主要介绍的内容就是变量的间接访问。
第8章 指针及其应用
第8章指针及其应用
学习目标
掌握指针的概念及基本操作,指针在数组和函数中的应用。
学习内容
指针、指针变量的概念,指针变量定义及使用,指针与一维数组, 指针与二维数组,指针与字符串,指针与函数。
下一页
返 回
第8章 指针及其应用
8.1 指针的基本用法 8.2 指针与数组 8.3 指针与函数 8.4 指针应用实例 8.5 本章小结 8.6 实训
8.1 指针的基本用法
程序运行结果:
【例8-2】从键盘上输入任意三个实数,利用指针的方法将这三个实 数按大小进行排序。 【编程思路】 (1)输入3个实数分别放到变量a、b、c中。 (2)3个指针变量p1、p2、p3分别指向变量a、b、c。 (3)比较变量的值,最终使p1指向最大值,p3指向最小值。 (4)按顺序输出p1、p2、p3所指向的变量的值。
8.2 指针与数组
printf("%5d",*p1);
printf("\n"); } 程序运行结果为:
上一页
下一页
返 回
8.2 指针与数组
8.2.2 指针与二维数组
1. 二维数组元素的地址 例如:int a[3][3]; 与一维数组名一样,二维数组名a也是数组的首地址。但是二者不同 的是,二维数组名的基类型不是数组元素类型,而是一维数组类型, 因此二维数组名a是一个行指针,其指向如图8-4所示。 二维数组a包含三个行元素:a[0]、a[1]和a[2],而它们又都是一维数 组名,因此也是地址常量,但是它们的基类型与数组元素类型一致。 第0行首地址:a[0] 第1行首地址:a[1] 第2行首地址:a[2]
8.1 指针的基本用法
{p=p1;p1=p3;p3=p;} if(b<c) {p=p2;p2=p3;p3=p;} printf("%.2f,%.2f,%.2f\n",*p1,*p2,*p3); } 程序运行结果:
该程序执行过程中,变量a、b、c的值始终未变,只是使指针p1最终 指向值最大的变量,使指针p3最终指向值最小的变量。 上一页 返 回
上一页
下一页
返 回
8.1 指针的基本用法
8.1.2 指针变量的定义和使用
1. 指针变量的定义 任何变量在使用前都必须定义,指针变量也一样。指针变量的一般定 义形式为: 基类型名 *指针变量名; 例如:int *p1,*p2; 说明: (1)定义了两个指针变量,变量名为p1和p2,这两个变量只能用来 存放地址。 (2)*是一个说明符用来说明定义的是指针变量,定义指针变量时必 须有。 (3)基类型表示指针变量所指向的变量的类型,也就是说,p1、p2 中只能存放整型变量的地址。 上一页 下一页 返 回
8.1 指针的基本用法
2. 指针变量的使用 (1)运算符“&”和“*” 运算符“&”为取地址运算符,后跟一个变量,表示取变量的地址。 比如,&a表示变量a的地址。 运算符“*”为间接访问运算符,后跟一个指针变量,表示取这个指 针变量所指向的变量的值。 (2)指针变量的赋值 通过给指针变量赋地址值,可以让指针变量指向某个变量。例如有以 下定义和语句: int a,b,*pa,*pb; pa=&a; /*指针变量pa指向变量a */ pb=&b; /*指针变量pb指向变量b*/ 上一页 下一页 返 回
上一页
下一页
返 回
8.1 指针的基本用法
【例8-1】通过指针变量访问整型变量。 【程序代码】 #include <stdio.h> void main( ) { int i,j,*pi; /*定义整型变量i和j,指针变量pi*/ i=10; pi=&i; /*使指针变量p指向变量i*/ j=*pi+5; /*通过指针变量访问变量i,等价于j=i+5;*/ printf("%d\n",i); printf("%d,%d\n",*pi,j); } 上一页 下一页 返 回
8.2 指针与数组
3. 数组元素的引用 针对数组元素地址的不同表示形式,数组元素的引用形式也有多种, 见表8-2。 下面语句通过数组名逐个输出数组a中各元素的值: for(i=0;i<10;i++) printf("%5d",*(a+i)); 这里首地址a始终指向数组元素a[0],并没有移动,通过变量i值的变 化来引用到每个元素。 下面语句通过移动指针来逐个输出数组a中各元素的值: for(p=a;p<a+10;p++) printf("%5d",*p);
上一页
下一页
返 回
8.2 指针与数组
所以a[0]+1就是数组元素a[0][1]的地址,a[1]+1是数组元素a[1][1]的地 址,那么任意的数组元素a[i][j]的地址是a[i]+j。 二维数组元素的地址表示形式较多,每种地址形式都有对应的数组元 素引用方法。比如: 数组元素地址:① &a[i][j] ② a[i]+j ③ *(a+i)+j 数组元素引用:① a[i][j] ② *(a[i]+j) ③ *(*(a+i)+j) 2. 指向二维数组元素的指针变量(列指针) 例如:int a[3][2],*p; p=&a[0][0]; 二维数组在内存中是按行顺序存储的,因此,可以通过对指向数组元 素的指针变量进行加减运算来达到引用任意数组元素的目的,引用方 法与引用一维数组元素一样。 上一页 下一页 返 回
8.2 指针与数组
8.2.1 指针与一维数组
1. 指针的移动 当指针变量指向一串连续的存储单元(即数组)时,可以对指针变量 加上或减去一个整数来进行指针的移动和定位。例如有如下语句: int a[5]={10,20,30,40,50},*p,*q; p=&a[0]; 指针p的指向情况如图8-2(a)所示。在此基础上,随着下面各个语句的 执行,指针p和q的指向会发生相应变化。 q=p+1; 如图8-2(a)所示,使指针变量q指向数组元素a[1] q++; 指针后移,指针变量q指向数组元素a[2] q+=2; 指针变量q指向数组元素a[4]
上一页
下一页
返 回
8.1 指针的基本用法
【程序代码】 #include <stdio.h> void main( ) { float a,b,c,*p1,*p2,*p3,*p; printf("请输入3个实数:"); scanf("%f,%f,%f",&a,&b,&c); p1=&a; p2=&b; p3=&c; if(a<b) {p=p1;p1=p2;p2=p;} if(a<c) 上一页 下一页 返 回
上一页
下一页
返 回
8.2 指针与数组
【例8-4】使数组中的元素逆序存放(不借助其它数组),要求用指 针的方法处理。 【编程思路】 (1)定义两个指针变量p1、p2,使p1指向第一个元素、p2指向最后 一个元素。 (2)将p1、p2所指向的数组元素的值互换,然后使p1指向第二个元 素、p2指向倒数第二个元素,再做上面的互换操作,这样重复下去, 直到p1指向了p2的后面或p1和p2指向了同一元素为止。 【程序代码】 #include <stdio.h> void main( ) { 上一页 下一页 返 回
下一页
返 回
8.2 指针与数组
q--; 指针变量q指向数组元素a[3] p++; 指针变量p和q的指向如图8-2 (b) 所示 现在如果有语句 i=*p;j=*q; 则i中的值为20,j中的值为40。若有语句 k=q-p; 则k中的值为2。表达式p<q的值为真,因为当前指针变量p中 存的地址值小于指针变量q中存的地址值。 2. 数组元素的地址 C程序中,数组名是数组的首地址,即第1个数组元素的地址,该地 址是地址常量,因此不能被修改或重新赋值,例如,对数组名a来说, a++; 或a=&a[2]; 都是错误的使用方法。 虽然不能对数组名进行赋值,但可以通过数组名来表示数组元素的地 址,从而也能达到引用数组元素的目的。 例如:int a[10],*p;p=a; 此时指针p指向数组a的第1个元素,如图8-3 所示。数组元素地址的几种表示形式见表8-1。 上一页 下一页 返 回
上一页
下一页
返 回
8.1 指针的基本用法
j=*p+1; /*取指针变量p所指向的存储单元中的值加1后赋给变量j,j的 值为11*/ *p=*p+1; /*取指针变量p所指向的存储单元中的值,加1后再放入p所 指向的存储单元中,也就是使变量i的值增1变为11*/
小测验 int a=11,b=22,*pa,*pb; pa=&a; pb=&b; 在上面程序段的基础上,执行语句pa=pb;和执行语句*pa=*pb;有什么不同?
8.2 指针与数组
int a[10],*p1,*p2,temp; printf("请输入10个数:"); for(p1=a;p1<a+10;p1++) /*输入一个整数,存放在p1所指的存 储单元中*/ scanf("%d",p1); for(p1=a,p2=a+9;p1<p2;p1++,p2--) /*通过交换首尾对应位置上 的值实现逆置*/ { temp=*p1; *p1=*p2;*p2=temp; /*两个指针变量所指向 的元素的值互换*/ } printf("逆序后数组的值: "); for(p1=a;p1<a+10;p1++) 上一页 下一页 返 回
上一页
返 回
பைடு நூலகம்
8.1 指针的基本用法
8.1.1 指针的概念
计算机的内存是以字节为单位的一片连续的存储空间,每个字节都有 一个编号,这个编号称为内存单元地址。这就如同旅馆的每个房间都 有一个房间号一样,如果没有房间号,旅馆的工作人员就无法进行管 理,同样没有字节编号,系统就无法对内存单元进行管理。 若在程序中定义了一个变量,系统就会根据变量的类型为变量在内存 中分配若干字节的存储空间,此后这个变量的单元地址也就确定了。 有了变量的地址,就可以立即找到该变量所在的存储单元并进行数据 的存取操作。这种通过变量地址存取变量值的方式称为变量的直接访 问。 程序中通常是通过变量名对变量进行访问,因为变量名是变量的符号 地址,它与单元物理地址之间的联系由系统自动建立。
上一页
下一页
返 回
8.2 指针与数组
float score[10],*p,sum=0,ave; printf("请输入10个学生成绩:"); for(p=score;p<score+10;p++) scanf("%f",p); for(p=score;p<score+10;p++) sum+=*p; /*取各成绩累加到sum 中*/ ave=sum/10; /*求平均成绩*/ printf("平均成绩=%.2f\n",ave); } 程序运行结果:
上一页
下一页
返 回
8.2 指针与数组
此语句在执行过程中,指针p首先指向元素a[0],输出操作输出的是第 一个元素的值,执行了p++后,指针指向了元素a[1],此时再做输出 操作,输出的是第二个元素的值,依次下去,指针会逐个指向每个元 素,再输出它们的值。当指针p指向最后一个元素后面的存储单元时, 循环结束。 【例8-3】有一个数组score ,存放10个学生的成绩,求平均成绩,要求 通过指针变量来访问数组元素。 【程序代码】 #include <stdio.h> void main( ) {
8.1 指针的基本用法
下面的定义和语句是错误的: float x; int *p; p=&x; 错误原因是x的类型和p的基类型不一致。 (3)通过指针变量引用变量 例如,有以下定义和语句: int i,j,*p; p=&i; *p=10; /*将10赋给p所指向的变量即变量i,等价于赋值语句i=10;*/