已阅读5页,还剩27页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1,第 九 讲,善于使用指针,2,一、地址和指针的概念 二、变量的指针(地址)和指针变量 三、数组与指针 四、字符串与指针 五、多维数组的指针 六、指向函数的指针 七、指针数组 八、指向指针的指针,主要内容:,3,一、指针的概念,1.数据在内存中的存储、读取过程 例如:整型变量i、j、k在编译时为变量分配内存,内存分配如图所示.,(2) 给变量赋值为 i=3; j=6; k=9;,(1) 假设变量 i,j,k 被分配的 内存地址分别为2000,2002,2004,(3) 通常,在程序中通过变量名对变量值进行存取。,其实程序经过编译后已将变量名转换为变量的地址,对变量值的存取都是通过变量的地址进行的。,图1,4,(1) 直接访问方式 按变量地址存取变量值的方式。 如果读取变量i的值,直接到为变量i分配的存储单元(2000、2001字节)中取出i的值(3)即可。,(2) 间接访问方式 先将变量i的地址存放在另一个变量p中,如果读取变量i的值,先找到变量p,从p中取出内容(2000,即变量i的起始地址),然后到2000、2001字节中取出i的值(3)。 即通过变量p访问为变量i分配的内存单元。,访问变量的两种方式:,5,直接访问示意图,间接访问示意图,表示将数值3送到变量i中,可有两种表达方法: (1)将3送到变量i所标志的单元中,即直接访问方式 (2)将3送到变量p所指向的单元(变量i)中。 即间接访问方式,注意:我们并不关心变量p的存储地址,对 变量p的访问属于直接访问。,6,二、 指针变量,1.变量的指针 变量的地址称为变量的指针(变量i 的指针为2000)。 2. 指针变量 存储变量地址的变量称为指针变量,用来指向另一个变量(P=&i) P是指针变量,指针变量的值即指针变量中存放的地址值 3. * 操作符 为了表示指针变量与它所指向的变量之间的关系,在程序中用 * 符号表示“指向”。,例如,P代表指针变量,* P则表示P所指向的变量的值。,以下两个语句作用相同: i=3; *P=3;,7,二、 指针变量(续),4.指针变量的定义,int i , j ; int *pointer1, *pointer2;,定义形式: 基类型 *指针变量名;,举例,说明p213:,(1)指针变量名前的*,表示该变量是指针型的变量。指针变量名为pointer1,而非 *pointer1。,(2)定义指针变量时必须指明基类型,用来指定该指针变量指向变量的类型。 (3)赋给指针变量的是变量地址而不能是任意类型的数据 (4)指针变量只能存放地址(指针),不要将一整数赋给一指针变量 int *pointer_1=100; (wrong),8,如何使一个指针变量指向一个变量呢?,使用取地址运算符 ,赋值语句pointer1=&i;实现将变量i的地址保存入指针变量pointer1中。如右图所示。,你能画出第二个赋值语句的示意图吗?,二、 指针变量(续),5.指针运算符 &,9,二、 指针变量(续),6.指针变量的引用,与指针变量有关的两个运算符: & : 取地址运算符 * :间接访问运算符,(1)上例将打印出i的值。 (2)*pointer1 与普通的整型变量一样使用,但前提是pointer1 必须已经明确地指向了某整型变量,或者说指针变量中必须已经存有了某整型变量的起始地址。,例如,i=3; pointer1=,说明,10,二、 指针变量(续),例8-2: 输入两个整数,按先大后小输出这两个整数,#include void main() int *p1, *p2, *p,a,b; scanf(“%d%d“, ,你能画出程序中指针处理过程的示意图吗?,11,二、 指针变量(续),7.指针变量作为函数参数,函数的实参值是地址,函数的形参应定义为指针类型,此时,实参和形参之间仍然是单向值传递方式。,#include (例8-3) void swap( int *p1, int *p2) int temp; temp=*p1; *p1=*p2; *p2=temp; void main() int a,b,*pointer1, *pointer2; scanf(“%d%d”, ,在被调函数中,通过间接访问,改变了 主调函数中实参指针变量所指变量的值。,变量a,b的地址被传递 到函数的形参变量p1,p2中,12,7.指针变量作为函数参数(例8-5),main( ) 例8-4 int a=3, b=5,*pointer1,*pointer2; pointer1= ,swap3(int *p1, int *p2) int *temp; temp = p1; p1 = p2; p2 = temp; ,输出: 3, 5,不能企图通过改变指针形参的值而使指针实参的值改变,即 形参的值如果发生改变,并不会改变主调函数的实参的值,调用前,调用后,/*temp?,13,三、数组与指针,数组在内存中占一片连续的存储区,该存储区的大小与数组的元素类型和数组长度有关。 每个数组元素占用相同大小的存储空间。 利用数组存储区的起始地址,可以逐个获得每个数组元素的存储地址。,例如,定义数组 int a10;,1.数组的存储,a0 a1 a2 a3 a4 a5 a6 a7 a8 a9,注:假设数组a的存储区起始地址为2000。,2000,2002,2004,2006,2000+4*2,2000+9*2,由上图可知,数组元素ai的存储地址的计算公式为: 数组a的起始地址+i元素类型占内存的字节数,图2,14,C语言规定: 数组名代表数组的起始地址,该地址在程序运行过程中不能修改。 即数组名a是个常量。,2.指向数组元素的指针,三、数组与指针,例如, int a10; int *p;,对指针变量p赋值:p= 则使p指向了数组的第一个元素。,因此,下面对指针变量p赋值的两个语句等价: p= /不是把数组a各元素的值赋给指针变量p,因此定义指向数组的指针变量时,可以对其初始化: int a10; int *p=a; (或 int *p=&a0;),15,三、数组与指针,例如,定义:int a10 ,*p=a; 可有如下操作: p=a; p=,3.通过指针变量引用数组元素,4.指针变量表达式和指针的算术运算符,(1) 可以对指针进行有限的算术运算,包括自增运算(+)、自减运算(- -)、加上一个整数、减去一个整数,以及减去一个指针变量。,(2)指针运算的结果依赖于指针所指向的对象的大小。,指针的算术运算的规则是: 当一个指针加上或减去一个整数时,指针并非简单的加上或减去该整数值, 而是加上或减去该整数与指针指向的对象的大小的乘积。,例如:int a10 ,*p=a; 则 p=p+1; 使指针变量的值更新为数组元素a1的地址,即p指向了数组元素a1。,16,注意:a+是错误的,为什么呢?,例如:int a10 ,*p=a,*q, x; 假定数组a的起始地址为2000,则下列每个操作后变量的值分别为多少?,三、数组与指针,p=p+1;,q=p;,q+=2;,x=q-p;,p+;,+p;,-p;,p的值为2002,p指向数组元素a1.,q的值为2002, q指向数组元素a1.,q的值为2006, q指向数组元素a3.,x 的值为4,p的值为2004, p指向数组元素a2.,p的值为2006 , p指向数组元素a3.,p的值为2004, p指向数组元素a2.,p-;,p的值为2002, p指向数组元素a1.,通过 -运算, 让指针变量指向数组中 的上一个元素。,得到: 从数组元素p到q相距字节数,通过+ 运算, 让指针变量指向数组中 的下一个元素。,指针的算术运算 除了用于数组外 没有什么意义,17,三、数组与指针,5.指针和数组的关系,C语言中数组与指针关系密切,它们几乎可以互换。数组名可认为是一个常量指针,指针可以完成涉及数组下标的操作。,例如:int a10 ,*p=a; 则,p指向数组的第一个元素,可用如下的指针表达式引用数组元素a3 *(p+3) 式中的 3 是对于指针变量p的偏移量。,当p指向数组的起始位置时,偏移量等于数组的下标。 *(p+3) 这种表示法称为“指针表示法” (或 *(a+3) ),因为*的优先级高于+,所以圆括号是必需的。,注意,总结,至此,引用一个数组元素,可以采用如下两种方法之一: (1) 下标法: 如ai (2) 指针法:如 *(p+i) 或 *(a+i),18,三、数组与指针,例:输出数组中的全部元素。(采用三种方法输出数组元素的值),#include void main() int a10 , i ; for(i=0; i10;i+) scanf(“%d“, ,#include void main() int a10 , i ; for(i=0; i10;i+) scanf(“%d“, ,#include void main() int a10 , i , *p; for(i=0; i10;i+) scanf(“%d“, ,1.下标法,2. 通过数组名计算数组元素的地址,找出元素的值,3. 用指针变量指向数组元素(例8-6/7),(1)用下标法直观; (2)用前两种方法效率一样; C编译系统是将ai转换为 *(a+i)来处理的 (3)用第三种方法省时间, p+操作快。,19,三、数组与指针,6.用数组名作函数的参数,(1) 实参数组名代表该数组首元素的地址。而形参是用来接收从实参传递过来的数组首元素的地址。因此,形参应该是一个指针变量(只有指针变量才能存放地址)。,(2) 虽然函数 f 的原型为 void f( int arr, int n) ,但编译时是将形参数组名arr按指针变量来处理的。即: void f( int arr, int n) void f( int *arr, int n) 等价,#include void main() int array10 ; . f(array,10); . ,void f( int arr, int n) . . ,首先回顾上一章“函数”中介绍的数组名作函数参数的情形:,说明:如果形参数组中 元素的值发生变化, 实参数组元素的值 随之变化。,说明P225:,20,三、数组与指针,例.将数组a中n个元素按相反的顺序存放。 (例8-8),#include void inv( int x , int n) / 形参为指针变量(*x)? int temp, i, j, m=(n-1)/2; for( i=0 ; i=m; i+) j=n-1-i ; temp=Xi; Xi=Xj; Xj=temp; return; void main() int i, a10=3,7,9,11,0,6,7,5,4,2; for( i=0; i10; i+) printf(“%d“,ai); inv(a , 10 ); /* 函数调用,实参为数组名*/ for(i=0;i10;i+) printf(“%d“,ai); ,a0 a1 a2 a3 a4 a5 a6 a7 a8 a9,a 数组,21,三、数组与指针,例.用选择法对10个整数按由小到大顺序排序。(例8-9),#include void sort( int *x, int n) /* 形参为指针变量,x 也可*/ int i, j, k,t; for(i=0; in-1; i+) k=i; for(j=i+1; jn; j+) if( *(x+j) *(x+k) ) k=j; if(k!=i) t=*(x+i); *(x+i)= *(x+k); *(x+k)=t; void main() int *p, i, a10; p=a; for( i=0; i10; i+,p+) scanf(“%d”,p); p=a; /* 思考?*/ sort(p , 10 ); /* 函数调用,实参为指针变量*/ for(i=0; i10; i+,p+) printf(“%d“,*p); ,a0 a1 a2 a3 a4 a5 a6 a7 a8 a9,a 数组,22,在C程序中,用两种方法访问字符串: (1)用字符数组存放一个字符串。 (2)用字符指针指向一个字符串。,1.字符串的表示形式,四、字符串与指针,#include void main() char string=“china! “ ; printf(“%sn“,string); ,#include void main() char *string=“china!“ ; printf(“%sn“,string); ,(1)用字符数组存放一个字符串。,(2)用字符指针指向一个字符串。,用字符串常量 初始化字符指针,用字符串常量 初始化字符数组,注意:,23,四、字符串与指针,2.访问字符串中的字符,#include void main() char a=“I love china!“ ,b20; int i; for(i=0; *(a+i)!=0; i+) *(b+i)=*(a+i); *(b+i)=0; printf(“%sn“,b); ,例.将字符串a复制为字符串b。(例8-11),用指针变量改写 见P232例8-12,24,3.字符指针作函数参数,四、字符串与指针,#include void copy_string(char *from, char *to) for( ; *from!=0; from+,to+) *to=*from; *to=0; void main() char *a=“I am a teacher“ ,b20; char *p=b; copy_string(a,p); printf(“%sn“,b); ,例. 用函数调用实现字符串a复制。 (例8-13),此循环可改为: while(*to=*from)!=0) to+; from+;,课后: 1)理解P236页7点说明 2)自学例8-14,25,五、多维数组的指针,1. 多维数组元素的地址 int a34=1,3,5,7, 9,11,13,15, 17,19,21,23;,a,a+1,a+2,a0,a0+1,a0+2,a0+3,行指针,列指针,a 第0行首地址 a+1,&a1 第1行首地址 a1,*(a+1) 第1行第0列元素地址 a1+2,*(a+1)+2,&a12 第1行第2列元素地址 *(a1+2),*(*(a+1)+2), a12 第1行第2列元素的值,行指针每加1,走一行,列指针每加1,走一列,26,例: 二维数组的有关数据(地址和值) int main() int a34=1,3,5,7,9,11,13,15,17,19,21,23;,printf(“%d,%dn”, a,*a); printf(“%d,%dn”, a0,*(a+0); printf(“%d,%dn”,printf(“%d,%dn”, a1, a+1); printf(“%d,%dn”,printf(“%d,%dn”,a10,*(*(a+1)+0)printf(“%d,%dn”,*a2,*(*(a+2)+0);,27,五、多维数组的指针(续),2. 指向多维数组元素的指针变量,main() int a34=1,3,5,7,9,11,13,15, 17,19,21,23; int *p; for(p=a0;pa0+12;p+) if(p-a0)%4=0) /控制换行 printf(“n”); printf(“%4d”,*p); ,(1)指向数组元素的指针变量,(2)指向由m个元素组成的一维数组的指针变量,逐个访问各元素时用此类指针,main() int a34=1,3,5,7,9,11,13,15, 17,19,21,23; int (*p)4, i, j; p=a; printf(“enter row and colum:“); scanf(“%d,%d”, ,行指针,aij,28,六、指向函数的指针,指向函数的指针变量,用来存放某一函数的起始地址,这意味着此指针变量指向该函数。,int (*p) (int, int);,p是指向函数的指针变量,它可以指向类型为整型且有两个整型参数的函数。,p=max; /把max函数的入口地址赋给了指针变量p,如果要用指针调用函数,必须先使指针变量指向该函数:,用函数指针
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 《模具设计与制造课程设计》教学大纲
- 建筑防火教研室教案
- 玉溪师范学院《数字电子技术》2021-2022学年期末试卷
- 数据终端设备账务处理实例-做账实操
- 冬季防火教育课件
- 房地产 -宋风古城商业景观氛围营造设计
- 2024年矿业测量仪器项目综合评估报告
- 2023年湿法加工合成云母粉项目评价分析报告
- 草坪地毯购买协议书范本
- 彩砖铺设协议书
- GA/T 145-2019手印鉴定文书规范
- 小学一年级家长会PPT1
- 企业员工职业道德培训(实用)课件
- 公文格式(全区)课件
- 输血查对制度-课件
- 痛经的中西医诊疗与护理考核试题及答案
- 吸收人类道德文明的优秀成果课件
- 2022年关于食品安全责任保险发展报告
- 解决方案销售课件
- 各类水质标准对照一览表
- 民族团结进步教育课件
评论
0/150
提交评论