C语言开发基础教程第6章-指针-教学PPT-课件.pptx
- 【下载声明】
1. 本站全部试题类文档,若标题没写含答案,则无答案;标题注明含答案的文档,主观题也可能无答案。请谨慎下单,一旦售出,不予退换。
2. 本站全部PPT文档均不含视频和音频,PPT中出现的音频或视频标识(或文字)仅表示流程,实际无音频或视频文件。请谨慎下单,一旦售出,不予退换。
3. 本页资料《C语言开发基础教程第6章-指针-教学PPT-课件.pptx》由用户(三亚风情)主动上传,其收益全归该用户。163文库仅提供信息存储空间,仅对该用户上传内容的表现方式做保护处理,对上传内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知163文库(点击联系客服),我们立即给予删除!
4. 请根据预览情况,自愿下载本文。本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
5. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007及以上版本和PDF阅读器,压缩文件请下载最新的WinRAR软件解压。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 语言 开发 基础教程 指针 教学 PPT_ 课件
- 资源描述:
-
1、第第6章章 指针指针指针与函数 指针数组 二级指针 指针概念 指针运算 指针与数组6.1 指针的概念程序运行过程中产生的数据都保存在内存中,内存是以字节为单位的连续存储空间,每个字节都有一个编号,这个编号称为内存地址。程序中的变量在生存期内都占据一定字节的内存,这些字节在内存中是连续的,第一个字节的地址就称为该变量的地址。6.1 指针的概念1、指针的概念定义一个int类型变量a:int a=10;a在内存中的存储如右图。6.1 指针的概念1、指针的概念编译器会根据变量a的类型int,为其分配4个字节地址连续的存储空间。假如这块连续空间的首地址为0 x0037FBCC,那么这个变量占据0 x00
2、37FBCC0 x0037FBCF这四个字节的空间,0 x0037FBCC就是变量a的地址。6.1 指针的概念1、指针的概念因为通过变量的地址可以找到变量所在的存储空间,所以说变量的地址指向变量所在的存储空间,地址是指向该变量的指针。6.1 指针的概念1、指针的概念存储变量a的内存地址为0 x0037FBCC,如果用一个变量保存该地址,如变量p,那么p就称为指向变量a的指针。6.1 指针的概念2、指针变量的定义定义指针变量的语法如下:变量类型*变量名;变量类型指定定义的指针指向的数据的类型,变量名前的符号“*”表示该变量是一个指针类型的变量。int*p;/定义一个int类型的指针变量多学一招:
3、内存四区多学一招:内存四区1、栈区栈区是一块连续的内存区域,该区域由编译器自动分配和释放,一般用来存放局部变量。栈区空间小,特点是先进后出。2、堆区堆区是不连续的内存区域,各块区域由链表将它们串联起来。该区域一般由程序员分配或释放,若程序员不释放,程序结束时可能由操作系统回收(程序不正常结束则回收不了)。堆区空间大,多学一招:内存四区多学一招:内存四区3、数据区数据区根据功能又可以分为静态全局区和常量区两个域。全局区(静态区)(static):用于存储全局变量和静态变量的区域,初始化的全局变量和静态变量在一块区域,未初始化的全局变量在静态变量的相邻区域。全局区在程序结束后由操作系统释放。常量区
4、:用于存储字符串常量和其他常量的区域,该区域在程序结束后由操作系统释放。多学一招:内存四区多学一招:内存四区4、代码区代码区用于存放函数体的二进制代码。程序中每定义一个函数,代码区都会添加该函数的二进制代码,用于描述如何运行函数。当程序调用函数时,就会在代码区寻找该函数的二进制代码并运行。6.2 指针运算指针的运算都是针对内存中的地址来实现的,主要包括取址运算、取值运算、加减运算、自增自减运算、同类指针相减运算。指针运算6.2.1 取址运算符在程序中定义变量时系统会为变量在内存中开辟一段空间,用于存储该变量的值,每个变量的存储空间都有唯一的编号,这个编号就是变量的内存地址。C语言支持以取址运算
5、符“&”获得变量的地址。6.2.1 取址运算符&符号的使用方法:&变量;int a=10;/定义变量a int*p=&a;/定义int类型的指针p,并取变量a的地址赋值给p6.2.1 取址运算符 小提示:指针变量的赋值在为指针变量赋值时,变量数据类型与指针的基类型最好相同,例如,将int型变量的地址赋值给int*型指针。如果将int型变量的地址赋值给float*型指针,程序虽然不会报错,但由于不同类型指针对应的内存单元数量不同,在解读指针指向的变量时会产生错误。6.2.2 取值运算符指针变量存储的数值是一个地址,直接对地址操作容易出错,针对指针变量的取值并非取出它所存储的地址,而是间接取得该地
6、址中存储的值。C语言支持以取值运算符“*”取得指针变量所指内存中存储的值。6.2.2 取值运算符*符号使用方法:*指针表达式int a=10;/定义变量a int*p=&a;/定义int类型的指针p,并取变量a的地址赋值给p int b=*p;/定义int型变量b,并取指针变量p中存储的变量值赋给b6.2.3 常用指针运算1、指针变量与整数相加减指针变量可以与整数进行相加或相减操作:p+n,p-np是一个指针变量,p+1表示将指针向后移动1个数据长度。数据长度是指针对应的基类型所占的字节数,也称为步长,若指针是int*类型的指针,则p的步长为4字节,执行p+1,则p的值加上4个字节,即p向后移
7、动4个字节。6.2.3 常用指针运算1、指针变量与整数相加减如果p为int*类型的指针变量,则p与p+1的位置如下图。p步长为4字节6.2.3 常用指针运算指针变量的加减运算实质上是指针在内存中的移动。6.2.3 常用指针运算对于单独零散的变量,指针的加减运算并无意义,只有指向连续的同类型数据区域,指针加、减整数才有实际意义,因此指针的加减运算通常出现在数组操作中。注 意6.2.3 常用指针运算2、指针表达式的自增自减运算指针类型变量也可以进行自增或自减运算:p+,p-,+p,-p指针的自增自减运算与指针的加减运算含意是相同的,每自增(减)一次都是向后(前)移动一个步长,即p+、+p最终的结果
8、与p+1是相同的。6.2.3 常用指针运算3、同类指针相减运算同类指针类型可以进行相减操作。pm-pnpm和pn是两个指向同一类型的指针变量。同类指针进行相减运算其结果为两个指针之间数据元素的个数,即指针的步长个数。6.2.3 常用指针运算同类指针之间只有相减运算,没有相加运算,两个地址相加是没有意义的,此外,不同类型指针之间不能进行相减运算。注 意多学一招:空指针、无类型指针、野指针多学一招:空指针、无类型指针、野指针空指针:没有指向任一存储单元的指针。有时可能需要用到指针,但是不确定指针在何时何处使用,因此先使定义好的指针指向空。int*p1=0;/0是唯一不必转换就可以赋值给指针的数据i
9、nt*p2=NULL;/NULL是一个宏定义,其作用与0相同 /在ASCII码中,编号为0的字符就是空多学一招:空指针、无类型指针、野指针多学一招:空指针、无类型指针、野指针无类型指针:使用void*修饰的指针。无类型指针指向一块内存,但其类型不定,程序无法根据这种定义确定为该指针指向的变量分配多少存储空间,所以若要使用该指针为其他基类指针赋值,必须先转换成其他类型的指针。void*p=NULL,*q;/定义一个无类型的指针变量int*m=(int*)p;/将无类型的指针变量p强制转换为int*型再赋值多学一招:空指针、无类型指针、野指针多学一招:空指针、无类型指针、野指针野指针:指向不可用区
10、域的指针。野指针的形成主要有以下两种原因:(1)指针变量没有被初始化。(2)若两个指针指向同一块存储空间,指针与内存使用完毕之后,调用相应函数释放了一个指针与其指向的内存,却未改变另一个指针的指向,将其置空。6.3.1 指针与一维数组1、定义一维数组指针数组在内存中占据一段连续的空间,对于一维数组来说,数组名默认保存了数组在内存中的地址,而一维数组的第1个元素与数组的地址是重合的,因此在定义指向数组的指针时可以直接将数组名赋值给指针变量,也可以取第1个元素的地址赋值给指针变量,另外,指向数组的指针变量的基类型与数组元素的类型是相同的。6.3.1 指针与一维数组1、定义一维数组指针有一个int类
11、型的数组:int a5=1,2,3,4,5;定义指向该数组的指针:int*p1=a;/将数组名a赋值给指针变量p1int*p2=&a0;/取第1个元素的地址赋值给指针变量p26.3.1 指针与一维数组小提示:数组名保存了数组的地址,其功能与指针相同,对数组名取值可以得到数组第1个元素。但数组名与指针又有不同,数组名是一个常量,不可以再对其进行赋值,另外,对数组名取地址得到的还是数组的地址6.3.1 指针与一维数组2、使用指针访问一维数组元素定义了指向数组的指针,则指针可以像使用数组名一样,使用下标取值法对数组中的元素进行访问。p下标 /下标取值法6.3.1 指针与一维数组2、使用指针访问一维数
12、组元素除了下标法,指针还可以通过“*”符号访问数组元素。6.3.1 指针与一维数组以访问数组int a5=1,2,3,4,5;为例(1)移动指针,使指针指向a2,获取指针指向元素的值。p=p+2;/将指针加2,使指针指向a2*p;/通过*运算符获取到a2元素指针p从数组首地址后移动了2个步长,指向了数组第3个元素。6.3.1 指针与一维数组数组是一段连续的内存空间,因此可以使指针在这段内存空间上进行加减运算,其内存图解如下图。6.3.1 指针与一维数组(2)不移动指针,通过数组元素指针间的关系运算指针并取值。*(p+2)/获取元素a2指针p还是指向数组首地址,以指针为依据,取后面两个步长处的元
13、素,即a2。6.3.1 指针与一维数组当指针指向数组时,指针与整数加减表示指针向后或向前移动整数个元素,同样指针每自增自减一次,表示向后或向前移动一个元素。当有两个指针分别指向数组不同元素时,则两个指针还可以进行相减运算,结果为两个指针之间的数组元素个数。6.3.1 指针与一维数组指针p1指向数组首元素,指针p2指向数组第4个元素,则执行p2-p1,结果为3,表示两个指针之间相差3个元素。这是因为指针之间的运算单位是步长,其实p1与p2之间的相差12个字节,即相差3个sizeof(int)。6.3.2 指针与二维数组二维数组与一维数组一样,可以使用指针指向二维数组,通过指针访问二维数组的元素。
14、6.3.2 指针与二维数组假设定义一个二行三列的二维数组:int a23=1,2,3,4,5,6;则数组a的逻辑结构与内存图解如右图。6.3.2 指针与二维数组1、定义二维数组指针与一维数组一样,二维数组的首地址与数组第1个元素是的地址是重合的,因此在定义指向二维数组的指针时,可以将二维数组的数组名赋值给指针,也可以取二维数组的第1个元素的地址赋值给指针。6.3.2 指针与二维数组1、定义二维数组指针二维数组指针的定义要比一维数组复杂一些,定义二维数组指针时需指定列的个数,其格式如下:数组元素类型(*数组指针变量名)列数;例如,定义指向二维数组a的指针:int(*p1)3=a;/二维数组名赋值
15、给指针p1 int(*p2)3=&a00;/取第一个元素的地址赋值给p26.3.2 指针与二维数组1、定义二维数组指针二维数组又可以看作每一行存储的元素为一维数组,在数组a中,a0是个一维数组,表示二维数组的第1行,它保存的也是一个地址,这个地址就是二维数组的首地址,因此在定义二维数组指针时,也可以将二维数组的第1行地址赋值给指针。int(*p3)3=a0;/取第一行地址赋值给 p36.3.2 指针与二维数组2、使用指针访问二维数组元素使用二维数组指针访问数组元素可以通过下标的方式:p00;/访问第1个元素6.3.2 指针与二维数组2、使用指针访问二维数组元素除了下标法,还可以通过移动指针来访
16、问二维数组的元素,在二维数组中,指针每加1,指针将移动一行,以数组a为例,若定义了指向数组的指针p,则p初始时指向数组首地址,即数组的第1行元素,若使p+1,则p将指向数组中的第二行元素。6.3.2 指针与二维数组2、使用指针访问二维数组元素二维数组指针移动的逻辑结构与内存图解如右图。6.3.2 指针与二维数组2、使用指针访问二维数组元素在二维数组a中,指针加1,是从第1行移动到了第2行,在内存中,则是从第1个元素移动到了第4个元素,即跳过了一行(3个元素)的距离。综上,在二维数组中,指针每加1,就移动1行,即移动二维数组中列的个数,如果每行有n个元素,则指针的移动距离为n*步长。6.3.2
17、指针与二维数组在二维数组a中,a0就表示第一行数据,a1表示第二行数据。a0、a1相当于二维数组中一维数组的数组名,指向二维数组对应行的第一个元素,a0=&a00,a1=&a10。6.3.2 指针与二维数组2、使用指针访问二维数组元素在二维数组的每一行中,首地址为ai,此时的ai相当于一维数组的数组名,类比一维数组中使用指针的基本原则,使ai+j,则可以得到第i行中第j个元素的地址,对其使用“*”操作符,则*(ai+j)表示二维数组中的元素aij。若类比取值原则对行地址ai进行转化,则ai可表示为a+i。6.3.2 指针与二维数组在二维数组中,a+i虽然指向的是该行元素的首地址,但它代表的是整
18、行数据元素,只是一个地址,并不表示某一元素的值。*(a+i)仍然表示一个地址,与ai等价。*(a+i)+j表示二维数组元素aij的地址,等价于&aij,也等价于ai+j。注 意6.3.2 指针与二维数组通过以上描述可知,使用指针访问二维数组中的元素有多种表示方法,例如定义指向二维数组的指针p,通过p访问二维数组a中的第2行第2列的元素:p11*(p1+1)*(*(p+1)+1)6.3.2 指针与二维数组二维数组中相关指针与数据的表示形式表示形式含义a二维数组名,指向一维数组a0,为0行元素首地址,也是a00的地址ai,*(a+i)一维数组名,表示二维数组第i行元素首地址,值为&ai0*(a+i
展开阅读全文