[理学]第7章 指针.ppt_第1页
[理学]第7章 指针.ppt_第2页
[理学]第7章 指针.ppt_第3页
[理学]第7章 指针.ppt_第4页
[理学]第7章 指针.ppt_第5页
已阅读5页,还剩44页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

7.1 指针的基本概念 7.2 指针与数组 7.2.1 指针与一维数组 7.2.2指针与二维数组 7.2.3指针与字符串 7.2.4指针数组 7.3程序举例,第7章 指针,7.1 指针的基本概念,7.1.1 指针的概念 1.内存地址(内存中存储单元的编号) float a5; 各元素的地址如图所示,2.变量地址的获取 变量地址:系统分配给变量内存单元的起始地址,通过取地址运算符 注意:&不能作用于常量、表达式或寄存器上 。,3.指针与指针变量,指针即地址。由于地址唯一确定程序实体的存储位置,就象路标一样,故形象地称为指针。,指针变量:专门存放变量(或其它程序实体)地址的变量。指针变量也需要存储单元,它本身也有地址。,4. 变量的访问方式 直接访问方式:通过变量名或其地址(如a或&a)访问变量的方式; 间接访问方式:通过指针变量(如p)访问它指向的变量(如a)的方式,7.1.2 指针变量的定义与初始化,1.指针的类型 指针的类型又称指针的基类型,即指针所指向的程序实体(如变量、数组)的类型,以此确定程序实体所占内存的字节数。指针即地址,无论基类型是什么,在VC下是需要4字节存储空间。,2.指针变量的定义 类型 *指针变量1,*指针变量2,; 例如: float *pi,*pj; 注意:“*”表示其后的变量是指针变量,而不是指针变量名的一部分。,7.1.2指针变量的定义与初始化,3.指针变量的初始化 指针变量没有赋值时值是随机的,被称为“野指针”。 给指针变量赋地址值的方法有: 定义指针变量时初始化赋值; 在程序执行部分赋值。 定义指针变量时初始化赋值形式为: 类型 *指针变量名=,7.1.3 指针的运算及引用,1.指针变量的赋值运算 (1) 赋给同类型普通变量的地址值。如: int k=10,*p,*q; q= 与scanf(“%d”,&k);作用相同。 (2) 通过已有地址值的指针变量赋值。例如在上面的程序段之后用:p=q;给p赋值,这时p和q指向同一个变量k,(3) 通过标准函数获得地址值(第9章有介绍) (4) 给指针变量赋“空”值,如:p=NULL;,2.指向运算和指针变量的引用 (1) 指向运算符* *指针 代表该指针所指向的存储单元的值,实现间接访问,因此又叫“间接访问运算符”。如: int a=5, *p; p=&a;printf(“%d“,*p); *p的值为5,与a等价。 *为单目运算符,优先级高、右结合性。 *运算符和取地址运算符&互逆: *(&a)=a &(*p)=p,7.1.3 指针的运算及引用,【注意】在不同的场合*号的作用不同: 在说明语句中,*表示其右边是指针变量; 在表达式中,作为双目运算符,*是乘法运算符;作为单目运算符,*是指向运算符。 (2)指针变量的引用 若有 int a=5, *p= &a ; 则 p与&a等价 *p与a等价,#include main( ) int a=10,*p= ,【例7-1】请理解下面程序中各语句的含义。,【分析】按题意,定义两个指针变量p1、p2,分别存入i1、i2的地址,当i1 main( ) int i1, i2, *p1, *p2, t; p1= ,【例7-2】输入两个整数i1和i2,利用指针将大数存放到i1中,小数存放到i2中,最后按i1、i2的顺序输出。,利用指针变量的指向操作交换i1、i2的值,若变量定义改为:int i1, i2, *p1, *p2, *p; 交换语句改为:if (i1i2)p=p1; p1=p2; p2=p;,但如果同时将输出语句改为: printf (“max=%d,min=%dn”,*p1, *p2); 可实现从大到小输出。 【思考2】如果将交换i1、i2值的语句改为: if (i1i2)*p=*p1; *p1=*p2; *p2=*p;结果将会怎样? 在i1i2的情况下,利用三个指针变量的指向操作交换i1、i2的值。问题是:指针变量p没有存放普通变量的地址,是野指针,因此也是错误的(运行时有警告)。,(1) 指针的算术运算 指针变量的+和- -运算; 指针加、减整数运算; 指向同一数组不同元素的指针相减运算。 (2) 指针的关系运算 指针的关系运算即比较指针(地址)大小的运算。有 = 等,其含义如下: if(pq) printf (“p在内存中q的低端。n“ ); if(p=q) printf (“p与q指向同一存储单元。n “ ); if(p=0)printf (“p指向 NULL。n “ );,3.指针的算术运算和关系运算,1.二级指针,定义:类型 *指针变量名; 例如: int *q,*p,x; 赋值:初始化;执行部分赋值 注 意:(1)一级指针变量只能取普通变量地址,二级指针变量取一级指针变量的地址,均不能赋整数值。 (2)引用普通变量 x 有三种方法:x ,*p,*q 。 *q=*(*q)=*p=x。 当然,引用前提是指针变量取得相应地址。,7.1.4 多级指针的概念,按照上述二级指针的思路,显然可以推广到三级指针、四级指针。使用多级指针变量的要点是: 多级指针变量均用基类型定义,定义几级指针变量要将变量名前放几个“*”号; 各指针变量均应取得低一级指针变量的地址后才能引用; 引用几级指针变量访问最终的普通变量时,变量名前需用几个指向运算符*号。,2.多级指针的概念,#include main() int *p1,*p2,*p3,*p4,x=10; p1= ,【例7-3】分析下面的程序,7.2 指针与数组,7.2.1 指针与一维数组 1.指向数组元素的指针变量 类型 *指针变量名,; 获得地址方法: 指针变量名=&数组元素; 或:指针变量名=一维数组名; 由于数组元素在内存中连续存放,知道一个元素的地址,特别是数组的首地址即数组名,就可求得其它元素的地址,以便对所有元素进行操作。,#include main() int a10, i, *p; printf(“输入10个数:n“); for(i=0; i10; i+) scanf(“%d“, ,【例7-4】用指针变量访问数组元素,2.一维数组元素的地址表示法,若有定义int a10, *p=a; 可用p和a表示所有元素及地址: 元素的地址 元素 p&a&a0 &p0 *p *aa0 p0 p+1a+1&a1&p1 *(p+1)*(a+1)a1p1 p+ia+i&ai&pi *(p+i)*(a+i)aipi 故一维数组元素有四种表示方法: 下标法 ai; 地址法 *(a+i); 指针变量法 *(p+i); 指针下标法 pi。 其中a为数组名(表示数组的首地址),其值不可改变;p为指针变量,必须取得数组名首地址,其值可变。,int *p; p = p 指向数组a的首元素,*(a+i),&ai,或: p = a;,p,p+i,*(p+i),ai的地址 &ai a+i 、p+i ai 相当于 *(a+i) *(p+i)、pi,#include main() int a10, i, *p=a; printf(“Enter ten numbers:n“); for(i=0; i10; i+) scanf(“%d“, a+i); for(i=0; i10; i+) printf(“%4d“, *(a+i); printf(“n”); for(i=0; i10; i+) printf(“%4d“, *(p+i); printf(“n“); for(;pa+10; p+) printf(“%4d“, *p); printf(“n“); p=a; for(i=0; i10; i+) printf(“%4d“, pi); printf(“n“); ,【例7-5】访问数组元素的几种方法,7.2.2指针与二维数组,二维数组元素是按行存放,可以按存放的顺序访问数组元素。 1.二维数组的地址表示法 二维数组由一维数组扩展形成,即一维数组的每一个元素作为数组名形成一行数组,各行数组的元素个数相同,是二维数组的列数。,行指针(二级) 列指针(一级) 元素 a&a0 *aa0&a00 a00*a0*a *a+1a0+1&a01 a01*(a0+1)*(*a+1) a+i&ai *(a+i)ai&ai0 ai0*ai*(a+i) *(a+i)+1ai+1&ai1 ai1*(ai+1)*(*(a+i)+1) ,1.二维数组的地址表示法,对m行n列的二维数组,元素aij可以表示为: aij*(ai+j)*(*(a+i)+j)(*(a+i)j 注意(*(a+i)j外面的“( )”不能省,否则(a+i)要先结合j。另外,也可以用a00的地址a0加顺序号n*i+j表示该元素为: aij*(a0+n*i+j)*(*a+n*i+j),#include main() int a34=1,2,3,4,5,6,7,8,9,10,11,12; printf(“%u,%un“,a, *a); printf(“%u,%un“,a+1, *a+1); /* 1行首地址和0行1列首地址*/ printf(“%u,%un“,a, ,【例7-6】输出二维数组的有关值,2.用于二维数组的指针变量,(1) 指向数组元素的指针变量(一级指针变量) 【例7-7】用一级指针变量输出二维数组全部元素。 由aij*(a0+n*i+j),将a0换成指针变量p。,#include main() int a34=1,2,3,4,5,6,7,8,9,10,11,12,i,j,*p; p=a0; for(i=0; i3; i+) for(j=0; j4; j+) printf(“%3d“, *(p+4*i+j); printf(“n“); ,#include main() int a34=1,2,3,4,5,6,7,8,9,10,11,12,i,j,*p; p=a0; for(i=0; i3; i+) for(j=0; j4; j+) printf(“%3d“, *p+ ); printf(“n“); ,方法2 一级指针p在数组内移动,2.用于二维数组的指针变量,(2) 指向一维数组的指针变量(行指针变量) 二维数组名(设为a)以及a+1、a+2等均为行指针(二级指针)常量,分别指向由一行元素组成的一维数组,但它们不能移动(例如不能由a+使a得到地址a+1)。 行指针变量的定义形式 类型 (*指针变量名)一维数组元素个数; 例 int a34, (*p)4; p=a;则有: pij*(pi+j)*(*(p+i)+j) (*(p+i)j=aij,#include main() int a34=1,2,3,4,5,6,7,8,9,10,11,12; int (*p)4=a, row, col; printf(“输入任意的行列号 :n“); scanf(“%d,%d“, ,【例7-8】输出二维数组任意行任意列的元素值,7.2.3指针与字符串,1.字符串的访问方法 字符类型的指针变量如果取得字符数组或字符串的首地址,也可以用来访问字符串,C语言访问字符串的方式有以下几种: (1) 直接引用常量字符串;/* 直接访问方式 */ (2) 字符数组方式; /* 直接访问方式 */ (3) 字符型指针变量方式引用常量字符串或字符数组。 /* 间接访问方式 */,#include main() char *s=“Hello World“; /* 定义字符型指针变量s且取得字符串首地址 */ char str=“Computer“,*p=str; /* 定义字符型指针变量p且取得字符数组首地址 */ puts(s); puts(p); /*分别输出两个字符串*/ ,【例7-9】理解下面程序中字符型指针变量的作用,#include main() char str80, *ps=str; int i; printf(“Input a string:n“); gets(ps); for(i=0; stri!= 0;i+) if(stri= k)break; if (stri!=0) printf(“k is %dth character.n“,i+1); else printf(“There is no k in the string.n“); ,【例7-10】在输入的字符串中查找是否有字符k,若有指出第一次遇到的k是第几个字符。,for(; *ps!= 0;ps+) if(*ps= k) break; if (*ps!=0) printf(“k is %dth character.n“,ps-str+1); else printf(“There is no k in the string.n“);,【算法分析】(例6-16) 删除字符串中的字符用覆盖算法,用for循环实现。将两个下标换成两个指针变量:指针变量p遍及字符串中的所有字符,表达式*q代表删除字符ch以后字符串中的字符。在表达式*q+中,q先结合+运算符,取地址值结合*后q自增。 注意对*q赋值是有条件的,这就实现删除全部ch字符。删除了ch字符后,最后要添加结束标志。 由于p、q都已移动,要用首地址str输出。,【例7-11】在输入的字符串中删除指定的字符。,#include main() char str80, *p, *q, ch; printf(“Input a string:n“); gets(str); printf(“Input a character you want delete:n“); ch=getchar( ); p=q=str; for(;*p!= 0;p+) if(*p!=ch) *q+=*p; *q=0; puts(str); ,i=j=0; for(;stri!=0;i+) if(stri!=c) strj+=stri; strj=0;,(1) 存储空间不同:字符数组存储全部字符和0;字符型指针变量存储字符串的首地址,4个字节。 (2) 性质不同:字符数组名为指针常量,不能移动;而字符型指针变量是变量,可以移动。若指向其它字符串,它代表的存储区域将改变。 (3) 改变字串方法不同:数组要逐个元素赋值或用strcpy函数;指针变量通过取得新字串首地址 (用“字符型指针变量=字符串”或“字符型指针变量=字符数组名”)。注意不能以“字符数组名=字符串”的形式。 用法:当需要存储一个字符串时用字符数组;访问字符数组或字符串时,可以用字符型指针变量(设为p)p代表下标或元素地址;*p代表元素(字符)。,字符数组和字符型指针变量,#include main() char str80, *p=str; int a=0,e=0,i=0,o=0,u=0; printf(“Input a string:n“); gets(str); while(*p!=0) switch(*p) case a: a+;break; case e: e+;break; case i: i+;break; case o: o+;break; case u: u+; p+; printf(“a:%d,e:%d,i:%d,o:%d,u:%dn“,a,e,i,o,u); ,【例7-12】输入字符串,统计各元音字母的个数,7.2.4 指针数组,1.指针数组的概念和定义 指针数组:由指向同一数据类型数据的指针为元素组成的数组。定义形式为: 类型 *数组名元素个数; 例如:int *num5; 定义了一维指针数组num,其元素是指向整型单元的指针变量。类似也可以定义二维指针数组,但使用较少。 指针数组的数组名也代表连续存储单元的首地址。由于数组元素是指针变量,因此,一维指针数组的数组名是二级指针常量。,【例7-13】阅读程序,#include main() int a4=2, 4, 6, 8, i; int *p4= ,【分析】本题中数组名p&p0为指针数组名首地址,*(p+i)pi=&ai是指针数组的元素,存放a数组元素的地址。*(p+i)*(pi)=ai为数组a的元素。,(1) 字符型指针数组可以通过初始化取得一批常量字符串的首地址,节约了存储空间(如图所示)例如: char *ps4 =“China“,“Japan“,“Korea“,“Australia“;,指针数组的作用,(2) 用指针数组元素访问字符串,可以利用循环,大大提高程序的效率。例如: for(k=0; k4;k+) puts(psk); (3) 通过调整指针数组元素指向,对字符串进行排序。,例7-14 利用指针数组对多字符串进行字典排序。 #include #include main( ) int i, j; char *ps4=“China“,“Japan“,“Korea“,“Australia“,*p; printf(“原顺序字符串:n“); for(i=0; i0) p=psi; psi=psj; psj=p; printf(“排序后的字符串:n“); for(i=0; i4; i+) puts(psi); ,2.用指针数组处理多字符串问题,程序运行结果如图所示:,【注意】用指针数组对字符串排序只是改变了指针数组各元素的指向,并没有改变原来各字符串的存储顺序。 另外,利用字符型指针数组不仅可以对字符串进行操作,也可以对任意字符串中的任意字符进行访问(例如ps0指向“China“中的C(首地址),ps0+1指向字符h,等等)。,3.通过指针数组访问二维数组,设有语句: int *p3, a34, i, j; for(i=0; i3; i+)pi=ai;有如下指针关系:,指针数组的数组名与二维数组的数组名一样,都是二级指针常量。根据上图有以下关系: pij*(pi+j)*(*(p+i)+j)(*(p+i)j *(p0+n*i+j)*(*p+n*i+j)=aij 上面的二维数组名a换成指针数组名p,pi是可移动的指针变量。 注意:使用指针数组与使用指向一维数组的指针变量处理二维数组问题在形式上很类似,但一定要注意它们的区别: (1)指向一维数组的指针变量是二级指针变量,指针数组名是二级指针常量; (2)指向一维数组的指针变量需要取得二维数组名首地址(二级指针常量);指针数组则需要让每个元素分别取得列指针(a0、a1,一级指针常量)。,#include main() int a33=1,2,3,4,5,6,7,8,9; int *pa3; int *p=a0, i; for(i=0; i3; i+) pai=ai; for(i=0; i3; i+) printf(“%d,%d,%dn“, ai2-i, *ai, *(*(a+i)+i); for(i=0; i3; i+) printf(“%d,%d,%dn“, *pai, pi, *(p+i); ,【例7-15】理解下面的程序,其中pi*(p+i)*(a0+i)*(&a0i)a0i,【例7-16】用指针的方法将数组a中的n个整数按相反的顺序存放,7.3 程序举例,#include void main() int a10=1, 2, 3, 4, 5, 6, 7, 8, 9, 10, *p, *q, temp; printf(“原数组为:n“); for(p=a; pa+10; p+) printf

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论