ImageVerifierCode 换一换
格式:DOCX , 页数:31 ,大小:111.14KB ,
资源ID:3540976      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/3540976.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(第五章 指针与结构.docx)为本站会员(b****3)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

第五章 指针与结构.docx

1、第五章 指针与结构第5章 指针与结构主要内容:指针概念与指针的简单运用;指针与数组(一维、二维数组),指向字符串的指针;结构的定义与引用,结构数组的运用。教学要求: 掌握指针与数组间关系 能用指针编写程序 掌握结构体的使用 能将指针与结构体混和使用,解决生活中的实际问题5.1 指针与指针的引用我们知道变量在计算机内是占有一块存贮区域的, 变量的值就存放在这块区域之中, 在计算机内部, 通过访问或修改这块区域的内容来访问或修改相应的变量。C语言中, 对于变量的访问形式之一, 就是先求出变量的地址,然后再通过地址对它进行访问,这也就是在这里所要论述的指针与指针变量。指针在C语言中运用非常广泛,原因

2、之一是较之其他方法,指针能设计出更加高效、灵活、简洁的代码,就好比一个学生的学号和姓名,它们都可以代表某一个学生,但是学号更通用,更规范.可以说指针是C语言中的精华。5.1.1 指针的概念要弄清楚什么是指针,必须先弄清楚数据在内存中的存储方式。 程序在执行过程中所需要处理的各种数据,都被存放在内存中。编译系统会根据程序中定义的变量的类型,分配一定长度的空间。例如,一般为整型变量分配两个字节,为字符型分配一个字节。为了方便管理,内存空间被划分成了若干个大小相同(1个字节)的存储单元,并且为每个存储单元安排了一个编号,这个编号被称为内存地址,它相当于旅馆的房间号,而在地址所对应的内存单元中存放数据

3、,这就相当于在旅馆房间号所对应的房间中居住旅客一样。请务必要弄清楚内存单元的地址和内存单元的内容这两个概念的区别。假设程序定义了两个整型变量 i,编译时系统分配2000和2001两个字节给变量i,2002和2003字节给变量j。并且将i赋值为5,j赋值为6。如图5-1所示,这时的表述是:变量i的值是5,变量i的地址是2000;变量j值是6,变量j的地址是2002;地址编号值2000520012002620032004图5-1 直接存取 在程序中一般是通过变量名来对内存单元进行存取操作的。其实程序经过编译以后已经将变量名转换为变量的地址,对变量值的存取都是通过地址进行的。例如有语句:j=i;它是

4、这样执行的:直接根据变量名与地址的对应关系(这个关系是编译时确定的),找到变量i的地址2000,然后从由2000开始的两个字节中取出数据(即变量的值5),然后把5直接存入变量j的地址为2002开始的两个内存单元中,这种按变量地址存取变量值的方式称为“直接访问”方式。在C语言中,还可以采用另一种称之为“间接访问”的方式,将变量i的地址存放在另一个变量中,在C语言中规定,可以在程序中定义一种特殊变量叫指针变量,专门用于存放地址。假设现定义了一个指针变量p,它被分配为3000和3001两个字节,同时定义了一个整型变量i,且变量i被分配的为2000和2001两个字节。可以通过下面语句将i的地址存放到p

5、中:p=&i;这时变量p的值就是2000,也就是变量i所占用的单元的起始地址。如果采取“间接存取”方式,要存取变量i的值,就必须先找到存放“i的地址”的变量p,从中取出i的地址(2000),然后到2000、2001字节取出i的值5,见图5-2: 图5-2 间接存取 由于通过地址能找到所需要的变量单元,我们可以说,地址指向该变量单元,因此,在C语言中,将地址形象化为指针。换句话说,一个变量的地址称之为该变量的“指针”,而指针变量是在一种专门存放其他变量在内存中的地址的特殊变量。指针变量的值是地址。5.1.2 指针变量的定义C语言规定所有变量必须遵循先定义后使用的规则。指针变量定义格式是:数据类型

6、 *指针变量名;例如: int *p; /*p是指向int 型变量的指针变量*/float *q; /*q是指向float 型变量的指针变量*/ char *a,b;/*其中a是指向char型变量的指针变量,而b是字符型一般变量*/ 那么,怎样使一个指针变量指向另外一个变量呢?可以用赋值语句使一个指针变量得到另外一个变量得地址,从而使它指向该变量。例如: int i; /*定义i为整型变量*/ int *p; /*定义p为指针变量*/ p=&i; /*将变量i的地址赋值给指针变量p*/ 注意 在定义指针变量时,要注意两点: 指针变量前面的“*”表示该变量的类型为指针变量。例如:int *p;指

7、针变量名是p,而不是*p,这是与定义整型或者字符型变量形式不同的。 在定义指针变量时必须指定基类型。并且指针变量的类型是它指向的内存单元中存放数据的类型,而不是指针变量的值的类型。那么既然指针变量,是用来存放地址的,为什么还要指定它的类型呢?要知道不同数据在内存中所占的字节数是不同的(例如:整型占2个字节,字符型占1个字节),在本章的稍后将要介绍指针的移动和指针的运算,例如“使指针移动1个位置”,那么这个1代表什么呢?如果一个指针指向的是一个整型数据,那么“使指针移动1个位置”意味着移动2个字节,如果一个指针指向的是一个字符型数据,那么“使指针移动1个位置”意味着移动1个字节。因此必须指定指针

8、变量的基类型,并且一个指针变量只能指向同一类型的变量。例如以下赋值是错误的:float a; /*定义a为float 型变量*/int *p; /*定义p为基类型为int的指针变量*/ p=&a; /*错误!将float型变量的地址存放到指向整型变量的指针变量中,*/【例5-1】 通过指针变量访问整型变量main()int a,b; /*定义a,b为整型变量*/int *p1,*p2; /*定义p1,p2为指向整型变量的指针变量*/a=100; /*为变量a赋值为100*/b=10; /*为变量b赋值为10*/p1=&a; /*将a的地址赋给p1*/p2=&b; /*将b的地址赋给p2*/pr

9、intf(%d,%dn,a,b); /* 输出a,b的值*/printf(%d,%dn,*p1,*p2); /*输出p1,p2所指向的变量的值*/运行结果为:100,10100,105.1.3 指针变量的引用1.深入理解两个运算符:* 与 &设有定义语句:int *p,a; “*”是指针运算符。“*p”出现在定义语句和非定义语句中的含义是不一样的!在定义语句中,星号 * 声明其后的变量p为一指针(地址)变量;在非定义语句中“*p”表示指针变量p指向的地址单元内的值。 “&”是地址运算符,“&a”表示取某一普通变量a的地址。很显然,*(&a) 与 a 相当。 p=&a; 表示将a的地址赋给了指针

10、变量 p,即p与&a指向了同一地址单元! 注意 “p=&a;”语句形式经常用到,使用时指针变量与一般变量的类型必须一致!例如本例中p,a均为整型变量,如果p,a的类型不一致那么就是错误的!“p=a;”是非法的语句,号两边变量意义不同,左边为指针变量,右边为普通变量。 C规定,不能直接将一个常数赋给指针变量(除0以外,代表空指针)。【例5-2】输入a、b两个整数,使用指针变量按大小顺序输出这两个整数。 main( ) int a,b,*p1,*p2,*p;p1=&a;p2=&b; scanf(%d,%d,p1,p2); /*等价于语句scanf(%d,%d, &a , &b);*/ if(*p1

11、*p2) /*判断a,b整数的大小*/ p=p1; p1=p2; p2=p;printf(a=%d,b=%dn,a,b); printf(max=%d,min=%dn,*p1,*p2); 运行情况如下:输入: 6,8输出: 6,8max=8,min=6 当输入6,8后,由于*p1 p1、p2 = p1。 指针与一个整型数据进行比较是没有意义的 。 不同类型指针变量之间比较是非法的。 零可以与任何类型指针进行=、!=的关系运算,用于判断指针是否为空指针 。例如:p1=0;作用是判断指针变量p1是否为空.5.2指针与数组从前面知道,一个数组包含有若干元素,数组各元素都在内存中占用存储单元,它们都有

12、相应的地址,而这些存储单元是连续的区域,数组名代表这块空间的起始地址。而指针变量既然可以指向地址,当然也可以指向数组元素的地址。通常人们习惯将数组的首地址存放到一个指针变量中,然后通过指针加减运算,存取数组各元素。如定义语句int x=1,2,3,4,5,*p=x;此语句中的“*p=x”,将x数组的首地址赋给了指针变量p,显然可以在定义语句中将它替换成“*p=&x0”形式。用指针来指向数组元素,比用纯数组的方式操作数组要方便得多,因为数组名不能运算,而指针是可以运算的。使用指针能使目标程序占内存少,运行速度快。5.2.1 指向一维数组的指针定义一个指向数组元素的指针的方法,与以前介绍的指向变量

13、的指针变量定义方法相同。例如:int a10; /*定义a为包含10个整型数据的数组*/int *p; /*定义p为指向整型变量的指针变量*/p=&a0; /*把元素a0的地址赋给指针变量p*/在C语言中规定数组名(不包含形参数组名,形参数组并不占有实际的内存单元)代表数组中首地址(即数组中第一个元素的地址)。因此,下面两个语句等价:p=&a0;p=a; 注意 指针变量指向数组并不是指向整个数组,而是指向了数组中第一个元素。上述“p=a;”的作用是:“把数组的首地址赋值给p”,而不是“把数组a各元素的值赋值给p”。 那么要通过指针引用数组元素,应该如何实现呢? 按C语言规定:如果指针变量p已指

14、向数组中的一个元素,那么p+1指向同一数组中的下一个元素,而不是简单的将p的值(地址)简单的加1。例如,数组元素是float型,每个元素占4个字节,那么p+1意味着使p的值(地址)加4个字节,以使它指向下一个元素;又例如数组元素是int型,每个元素占2个字节,那么p+1意味着使p的值(地址)加2个字节,以使它指向下一个元素。也就是说,p+1所代表的地址实际上使p+1d,d代表一个数组元素所占的字节数。根据上述,引用一个数组元素可以用两种方法:(1) 下标法,如a0形式;(2) 指针法,如*(a+i)或者*(p+i)。其中a是数组名,p是指向数组元素的指针变量,初值为数组a的首地址。例如有语句如

15、下:int a10,*p; 数组名是该数组的指针 a是数组的首地址(即a0的地址),是一个指针常量。a = &a0,a+1 = &a1, ,a+9 = &a9 数组元素的下标表示法:a0,a1, ,ai, ,a9 数组元素的指针表示法: *(a+0),*(a+1), ,*(a+i), ,*(a+9) 指向一维数组元素的指针变量由于数组元素也是一个内存变量,所以此类指针变量的定义和使用与指向变量的指针变量相同。 例如有语句如下:int a10,*p;p = a; /*相当于p = &a0;*/此时p指向a0,下面用p表示数组元素 下标表示法: p0,p1, ,pi, ,p9 指针表示法: *(p

16、+0),*(p+1), ,*(p+i), ,*(p+9) 提醒用指针变量引用数组元素,必须关注其当前值。如果指针变量p的初始值不一样,那么用p表示数组元素时,有一定的差异.例如:p = p + 3;此时,指针变量p指向第四个数组元素a3,那么p0 、 *(p+0)等价于a3,而*(p-1)、p-1等价于a2; *(p+1) 、p1等价于a4,依次类推.【例5-3】输出一维数组中的所有元素。main() int a=1,2,3,4,5,*p, i;p=a; /*将数组a的首地址赋值给指针变量p*/ for(i=0;i5;i+) printf(n %d,%d,%d,%d,ai, *(a+i),pi

17、, *(p+i) ); 程序分析与解释:程序中的printf()函数展示了对一维数组元素的四种等价表示形式。假如数组a的首地址是2000,那么p指向内存单元2000,则该数组在内存中存放形式及数组元素的表示形式如图5-4所示:【例5-5】 输入五个整数,使用指针变量将这五个数按从小到大排序后输出。 main( ) int a5,*pp,*p,*q,t;for (p=a; pa+5;p+) /*输入5个整数,并且分别存放到数组a中*/ scanf(%d,p); for (p=a; pa+4; p+) /*使指针变量p指向数组a*/ pp=p; for (q=p+1; q*q) pp=q; if

18、(pp!=p) /*如果本轮比较出的较小值不等于*p,那么交换值*/ t=*p;*p=*pp; *pp=t; for (p=a; pa+5; p+) printf(%d ,*p); /*输出数组的值,并且每输出一个空一格*/ 运行情况如下:输入:54 65 12 34 2输出:2 12 34 54 65该问题的解决方法,采取的是在上一章所学的选择排序法来进行排序的.5.2.2 指向二维数组的指针1. 二维数组的地址 例如有定义语句:int a33; 二维数组名a是数组的首地址。 二维数组a包含三个行元素:a0、a1、a2 。 三个行元素的地址分别是:a、a+1、a+2。而a0、a1、a2也是地

19、址量,是一维数组名,即*(a+0)、*(a+1)、*(a+2)是一维数组首个元素地址。如图5-5: 2. 二维数组元素的地址 a0、a1、a2是一维数组名,所以ai+j是数组元素的地址。数组元素aij的地址可以表示为下列形式, &aij、ai+j 、*(a+i)+j如图5-6所示: 3.二维数组元素的表示法数组元素可用下列形式表示:aij、*(ai+j)、*(*(a+i)+j)a 是二维数组,根据C的地址计算方法,a经过两次 * 操作才能访问到数组元素。所以: * a 是 a0,* * a 才是 a00。 看一看,想一想 若a是二维数组名请理解下列表示方法的含义aa0,*(a+0),*a,&a

20、00a+1,&a1a1+2,*(a+1)+2,&a12 a0是a00的地址,*a0是a00。4. 指向二维数组元素的指针变量【例5-6】用指向数组元素的指针变量输出数组元素,请注意数组元素表示方法。 main( ) int a34=0,1,2,3,10,11,12,13,20,21,22,23, i, j, *p; for (p=a0, i=0; i 3; i+) for (j=0; jstrlen(str) | n=0 | m=0) printf(NULLn); else for (p=str+m-1,i=0; in; i+) if(*p) ci=*p+; else break; /* 如读

21、取到 0 则停止循环 */ ci=0; /* 在c数组中加上子串结束标志 */ printf(%sn,c); 5.3结构体在前面,已经介绍过了基本数据类型的变量(如整型、字符型、浮点型变量),也介绍了一种构造类型数据数组,其中数组中各元素属于同一种类型。但是只有这些数据类型是不够的,有时需要将不同数据类型组合成一个有机的整体,以便引用。这些组合在一个整体中的数据是互相联系的,例如:一个学生的信息有学号、姓名、性别、年龄、住址、成绩等; 一本图书的信息有分类编号、书名、作者、出版社、出版日期、价格、库存量等。那么如何描述这些类型不同的相关数据呢?在C语言中允许用户自己指定这样一种数据结构,它是由若干个类型不同的(当然也可以相同)的数据项组合在一起,称为结构体(structure)。构成结构体的各个数据项称为结构体成员。 它相当于其他高级语言中的“记录”。如果要用C语言编写实用程序,结构的知识是不可缺少的!同时,结构还是C+等后续语言的基础。5.3.1 结构体的定义与引用1结构体定义的一般格式struct 结构体名 数据类型1 成员名1; 数据类型2 成员名2; 数据类型n 成员名n; ; 提醒 不要忽略了最后的分号。 struct为关键字; 结构体名是用户定义的类型标识,用作结构体类型的标志。 结

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1