《指针与动态内存分配》由会员分享,可在线阅读,更多相关《指针与动态内存分配(23页珍藏版)》请在金锄头文库上搜索。
1、1-1指针与动态内存分配Stillwatersrundeep.流静水深流静水深,人静心深人静心深Wherethereislife,thereishope。有生命必有希望。有生命必有希望1-2课程内容安排课程内容安排指针概述指针概述 指针的运算指针的运算 指针与数组指针与数组 指针与函数指针与函数 指针与字符串指针与字符串 二级指针二级指针 动态内存分配动态内存分配小结小结 习题习题 1-31 1 指针概述指针概述 1.1.内存单元内存单元:在计算机中,所有的数据都是存放在存储器中的。一在计算机中,所有的数据都是存放在存储器中的。一般把存储器中的般把存储器中的一个字节称为一个内存单元一个字节称为
2、一个内存单元,不同的数据类型所占,不同的数据类型所占用的内存单元数不等,如整型量占用的内存单元数不等,如整型量占2 2个单元,字符量占个单元,字符量占1 1个单元等。个单元等。为了正确地访问内存单元,必须为每个内存单元编上号。根据一个内存单元的编号即可准确地找到该内存单元。内存单元的内存单元的编号也叫做地址编号也叫做地址。简单来说,指针是一个地址,其指向存储某一个数据的存储地简单来说,指针是一个地址,其指向存储某一个数据的存储地址。址。指针变量是一种特殊性质的变量。指针变量是一种特殊性质的变量。指针变量是存放另一个变量的地址的变量。它和普通变量一样占用一定的存储空间。它与普通变量不同之处:指针
3、的存储空间里存放的不是普通的数据,而是一个地址。对于指针我们可以这样理解,比如一个人要到某地去,但不认对于指针我们可以这样理解,比如一个人要到某地去,但不认识路,于是去问交警。然后交警把该地方的地址写在了一张纸识路,于是去问交警。然后交警把该地方的地址写在了一张纸上,并且给了该问路人。那么交警写的地址就是指针,指向要上,并且给了该问路人。那么交警写的地址就是指针,指向要去的地址,而那张纸就是指针变量,用于存储指针。去的地址,而那张纸就是指针变量,用于存储指针。 1-42 2 定义指针定义指针 指针是一个变量,在程序中使用时,必须先声明,后使用。指针是一个变量,在程序中使用时,必须先声明,后使用
4、。在指针声明的同时也可以进行初始化。指针的定义指出了在指针声明的同时也可以进行初始化。指针的定义指出了指针的存储类型和数据类型,定义的语法形式如下:指针的存储类型和数据类型,定义的语法形式如下:存储类型名存储类型名数据类型数据类型*指针变量名指针变量名例如:int *px;char *name;static int *pa;定义了一个指针后,在使用此指针前,必须首先给它赋一定义了一个指针后,在使用此指针前,必须首先给它赋一个合法的值。否则,程序中对指针的使用就有可能导致系个合法的值。否则,程序中对指针的使用就有可能导致系统崩溃。可以在定义指针的同时通过初始化来给指针赋值,统崩溃。可以在定义指针
5、的同时通过初始化来给指针赋值,也可以在使用之前给指针赋值。指针初始化的一般形式如也可以在使用之前给指针赋值。指针初始化的一般形式如下:下:存储类型存储类型数据类型数据类型*指针名指针名=初始地址值初始地址值;1-53 3 指针的运算指针的运算 两个有关的运算符:两个有关的运算符:(1)&:取地址运算符:取地址运算符(2)*:指:指针运算符(或称运算符(或称“间接接访问”运算符)运算符)例如,例如,&为变量的地址,量的地址,*为指指针变量所指向的量所指向的变量量使用使用*p与与定定义*p不同,定不同,定义时,int*p中的中的“*”不是运算符,而不是运算符,而在程序在程序执行行语句中,句中,引用
6、引用“*p”,其中的,其中的“*”是一个指是一个指针运算符运算符指针运算是以指针变量所持有的地址值为运算量进行的运指针运算是以指针变量所持有的地址值为运算量进行的运算。因此,指针运算的实质是地址的计算。由于指针是持算。因此,指针运算的实质是地址的计算。由于指针是持有地址量的变量这一特性,指针的运算与普通变量的运算有地址量的变量这一特性,指针的运算与普通变量的运算在种类上和意义上都是不同的。指针运算的种类是有限的,在种类上和意义上都是不同的。指针运算的种类是有限的,它只能进行它只能进行取地址和取值运算、算术运算、关系运算和赋取地址和取值运算、算术运算、关系运算和赋值运算值运算。如果说明了一个指针
7、,并使其值为某个变量的地址,则可如果说明了一个指针,并使其值为某个变量的地址,则可以通过这个指针间接地访问在这个地址中存储的值。以通过这个指针间接地访问在这个地址中存储的值。1-64 4 常指针与指针常量常指针与指针常量修修饰词constconst是是C语言的一种关言的一种关键字,起受保字,起受保护,防止以外的,防止以外的变动的作用!可以修的作用!可以修饰变量,参数,返回量,参数,返回值,甚至函数体。甚至函数体。const修修饰变量,表示量,表示该变量不能被修改。量不能被修改。1、constchar*p表示表示指向的内容不能改指向的内容不能改变,叫常量,叫常量指指针。2、char*constp
8、,就是将就是将p声明声明为指指针常量,它的地常量,它的地址不能改址不能改变,是固定的,但是它的内容可以改,是固定的,但是它的内容可以改变。3、若、若const指指针是前两种的是前两种的结合合,使得指向的内容和地使得指向的内容和地址都不能址都不能发生生变化化.constdoublepi=3.14159;constdouble*constpi_ptr=π教材教材54到到55页1-75 5 多级指针多级指针当指当指针变量量pp所指的所指的变量量ip又是一个指又是一个指针时,pp是一是一种指向指种指向指针的指的指针,此,此时称指称指针变量量pp是一种多是一种多级指指针。定。定义指向指指向指针变量
9、的指量的指针变量的一般形式量的一般形式为:类型型说明符明符*变量名;量名;该一般形式一般形式说明以下几个方面的内容:首先定明以下几个方面的内容:首先定义变量量为指指针变量,其次是量,其次是该变量能指向一种指量能指向一种指针对象,最象,最后是被指向的指后是被指向的指针对象能指向的象能指向的对象的象的类型。型。例如例如int*pp,*ip,i;ip=&i;pp=&ip;定定义说明明pp是指向指是指向指针的指的指针变量;它能指向的是量;它能指向的是这样一种指一种指针对象,象,该指指针对象是能指向象是能指向int型的指型的指针变量。如上述代量。如上述代码让pp指向指指向指针变量量ip,ip指向指向整型
10、整型变量量i。1-86 6 指针的算术运算指针的算术运算 指指针的算的算术运算是按运算是按C语言地址言地址计算算规则进行的,行的,这种种运算与指运算与指针指向的数据指向的数据类型有密切关系,也就是型有密切关系,也就是C语言言的地址的地址计算与地址中存放的数据算与地址中存放的数据长度有关度有关。设px和和py是指向具有相同数据是指向具有相同数据类型的一型的一组若干数据的指若干数据的指针,n是是整数,整数,则指指针可以可以进行的行的算算术运算运算有如下几种:有如下几种:px+n,pxn,px+,+px, pxpx,pxpx,pxpxpypy1-9指指针与整数运算与整数运算指指针作作为地址量加上或减
11、去一个整数地址量加上或减去一个整数n,其意,其意义是指是指针当当前指向位置的前方或后方第前指向位置的前方或后方第n个数据的位置个数据的位置。由于指。由于指针可可以指向不同数据以指向不同数据类型,即数据型,即数据长度不同的数据,所以度不同的数据,所以这种种运算的运算的结果果值取决于指取决于指针指向的数据指向的数据类型。例如,假型。例如,假设有有一一单字字节字符字符类型和另一个双字型和另一个双字节整数整数类型:当字符指型:当字符指针加加1时,增量,增量为1,而整数指,而整数指针加加1时,增量,增量为2。指指针相减:相减:设指指针p和和q是指向同一是指向同一组数据数据类型一致的数据,型一致的数据,则
12、pq运算的运算的结果果值是两指是两指针指向的地址位置之指向的地址位置之间的数据个数。的数据个数。1-10两个指向同一组类型相同的数据的指针之间可以进行各种关系运算,运算结果为逻辑值,满足关系时,结果为(真),否则为(假)。如int a10,*p,*q; p=&a0; q=&a3; 则p&a2 结果为0指向不同数据类型的指针之间的关系运算是没有意义的。指针与一般整数变量之间的关系运算也是无意义的。但是指针可以和零之间进行等于或不等于的关系运算,即:p= =0或p!=0,它们用于判断指针p是否为一个空指针。1-117 7 指针与数组指针与数组 指针在数组中使用较为频繁,事实上,数组名就是一个地址,
13、表示的是该数组的首地址 。要访问或使用一个数组元素,可以用三种不同的方法:要访问或使用一个数组元素,可以用三种不同的方法:下标法、地址法,还有一种是指针法。下标法、地址法,还有一种是指针法。 可以设置指针变量指向数组或数组中的元素。 如:int a10, *p; 可以使整型指针p指向数组中任何一个元素, 假定给出赋值运算 p=&a0; 此时, p指向数组中的第0号元素, 即a0, 指针变量p中包含了数组元素a0 的地址, 由于数组元素在内存中是连续存放的, 因此, 我们就可以通过指针变量p及其有关运算间接访问数组中的任何一个元素。根据地址运算规则, a+1为a1的地址, a+i就为ai的地址。
14、 1-12在在定义指向数组的指针定义指向数组的指针时,有下列几种表示方式:时,有下列几种表示方式:(1)inta10,*p=&a0;(2)inta10,*p=a;(3)inta10,*p;p=a;(4)inta10,*p;p=&a0;(5)inta10;int*p=&a0;用指针表示数组元素的地址和内容的几种形式:用指针表示数组元素的地址和内容的几种形式:(1).p+i和和a+i均表示均表示ai的地址的地址,或者讲或者讲,它们均指向数组第它们均指向数组第i号元号元素素,即指向即指向ai。(2).*(p+i)和和*(a+i)都表示都表示p+i和和a+i所指对象的内容所指对象的内容,即为即为ai。
15、(3).指向数组元素的指针指向数组元素的指针,也可以表示成数组的形式也可以表示成数组的形式,也也就是说就是说,它允许指针变量带下标它允许指针变量带下标,如如pi与与*(p+i)等等价。价。练习教材练习教材57页页5-5例题例题。1-138 8 指针数组指针数组数数组组中每个元素都是指中每个元素都是指针变针变量,量,该该数数组组就称就称为为指指针针数数组组。指指针针数数组组的定的定义义形式形式为为:类类型型标识标识*数数组组名名整型常量表达式整型常量表达式;例如例如:int*a10;定定义义了一个指了一个指针针数数组组,数数组组中的中的每个元素都是指向整型量的指每个元素都是指向整型量的指针针,该
16、该数数组组由由10个元素个元素组组成成,即即a0,a1,a2,.,a9,它它们们均均为为指指针变针变量。量。a为该为该指指针针数数组组名名,和数和数组组一一样样,a是常量是常量,不能不能对对它它进进行增量运算。行增量运算。a为为指指针针数数组组元素元素a0的的地址地址,a+i为为ai的地址的地址,*a就是就是a0,*(a+i)就是就是ai。1-149 9 指向数组的指针指向数组的指针int*a10;定定义了一个指了一个指针数数组,本,本质是一个数是一个数组,每个元,每个元素都是指素都是指针。int(*p)10;a为指向含指向含10个元素的一个元素的一维整型数整型数组的指的指针变量量。指向数指向
17、数组的指的指针是一个二是一个二级指指针。1-151010 指向二维数组指针的应用指向二维数组指针的应用intmain()inttwoArray34=0,1,2,3,4,5,6,7,8,9,10,11;int(*p)4=twoArray;/定定义一个指向一一个指向一维数数组的指的指针for(p=twoArray;p!=twoArray+3;+p)/第一第一层循循环,每个循,每个循环遍遍历一行元素一行元素for(int*q=*p;q!=*p+4;+q)/第二第二层循循环,每次循,每次循环输出一个元素出一个元素cout*q;coutendl;return0;1-16上上图表示了二表示了二维数数组的存
18、的存储方法,方法,twoArray0twoArray2表示各一表示各一维数数组的首地址,二的首地址,二维数数组名名twoArray表示整个二表示整个二维数数组的首地址,它和的首地址,它和twoArray0以及以及twoArray00是同一个地址。但是他是同一个地址。但是他们表示的表示的级别是不同的,因此不能混用。是不同的,因此不能混用。twoArray1是元素是元素级别的,是的,是int*,而而&twoArray1是是行行级别的,是的,是int(*p)4。也就是也就是说,如果,如果对twoArray1加加1,那么指,那么指针移移动到下一个元素的位置,而如果到下一个元素的位置,而如果对&twoA
19、rray1加加1,指,指针移移动到下一行的位置:到下一行的位置:1-171111 指针与字符串指针与字符串字符串常量是由双引号括起来的字符序列字符串常量是由双引号括起来的字符序列,C+语言中操作一言中操作一个字符串常量的方法有个字符串常量的方法有:(1).把字符串常量把字符串常量存放在一个字符数存放在一个字符数组之中之中,例如例如:chars=astring;数数组s共有共有9个元素所个元素所组成成,其中其中s8中中的内容是的内容是0。实际上上,在字符数在字符数组定定义的的过程中程中,编译程序直接程序直接把字符串复写到数把字符串复写到数组中中,即即对数数组s初始化。初始化。(2).用用字符指字
20、符指针指向字符串指向字符串,然后通然后通过字符指字符指针来来访问字符串存字符串存贮区域。当字符串常量在表达式中出区域。当字符串常量在表达式中出现时,根据数根据数组的的类型型转换规则,它被它被转换成字符指成字符指针。因此。因此,若我若我们定定义了一字符指了一字符指针cp:char*cp;于是可用于是可用:cp=“astring”;使使cp指向字符串指向字符串常量中的第常量中的第0号字符号字符a,以后我以后我们可通可通过cp来来访问这一存一存贮区域区域,如如*cp或或cp0就是字符就是字符a,而而cpi或或*(cp+i)就相当于字符串的第就相当于字符串的第i号字符号字符。1-181212 动态内存
21、分配动态内存分配在在C语言言中中使使用用“malloc()”函函数数来来申申请内内存存,使使用用“free()”函函数数来来释放放内内存存。在在C+语言言中中依依然然可可以以使使用用这种种方方法法,但但是是不不建建议使使用用该方方法法。C+语言言提提供供了了new表达式和表达式和delete表达式来申表达式来申请和和释放内存。放内存。用用new表表达达式式创建建动态的的类对象象,它它的的寿寿命命期期由由创建建开开始始,释放放时结束束,定定义格格式式为,“new();”,其其中中初初始始值是是可可选项,若若给出出了了初初始始值,系系统会会自自动调用用相相应的的构构造造函函数数初初始始化化新新创建
22、建的的类对象,否象,否则调用缺省构造函数用缺省构造函数进行初始化。行初始化。1-19例如,例如,int*p;/整数整数类型指型指针float*f;/浮点浮点类型指型指针p=newint;/为一个整数一个整数类型的数分配内存型的数分配内存f=newfloat; /为一个浮点一个浮点类型的数分配内存型的数分配内存如如果果成成功功调用用了了new,则返返回回一一个个指指向向已已分分配配空空间的的指指针,如如果果此此空空间不不可可用用或或检测到到某某些些错误,则返返回回零。零。为对象分配内存使用同象分配内存使用同样的的语法,例如,法,例如,person*stu_ptr;/指向指向类型型为person对
23、象的指象的指针stu_ptr=newperson(); /指向新的指向新的person对象象如如果果不不再再需需要要所所分分配配的的存存储空空间,要要用用delete释放放,例例如:如:deletep;deletef;1-20动态改改变数数组的大小:的大小:int*a=newint40;for(inti=0;i40;i+)ai=i;for(inti=0;i40;i+)coutaiendl;1-21本章主要介绍了本章主要介绍了C+中较为复杂的指针的基本内容。以前中较为复杂的指针的基本内容。以前接触过接触过C语言的读者应该知道,指针是语言的读者应该知道,指针是C语言中最难掌握语言中最难掌握的,也是
24、最灵活的。本章一开始就通过一个示例介绍了指的,也是最灵活的。本章一开始就通过一个示例介绍了指针的概念和作用,接下来主要介绍了指针的运算,包括通针的概念和作用,接下来主要介绍了指针的运算,包括通过指针取值(过指针取值(*)、取地址()、取地址(&)、指针的算术运算和关)、指针的算术运算和关系运算等。此外,本章重点介绍了指针的应用,主要包括系运算等。此外,本章重点介绍了指针的应用,主要包括指针在数组中的应用、在字符串中的应用和指向指针的应指针在数组中的应用、在字符串中的应用和指向指针的应用。最后,就动态内存分配和引用作了简要介绍。用。最后,就动态内存分配和引用作了简要介绍。小结小结1-221 1写
25、出下列程序的运行结果。写出下列程序的运行结果。#include #include void main()void main() int *p; int *p; int n = 100; int n = 100; p=&n; p=&n; coutn=nendl; coutn=nendl; cout*p=*pendl; cout*p=*pendl; 2 2编编写写一一个个C+C+程程序序,接接收收从从键键盘盘输输入入的的1010个个整整数数,用用指针求这指针求这1010个数中的最大数、最小数和平均值。个数中的最大数、最小数和平均值。 习题习题1-23习题习题3.以下程序的输出结果是以下程序的输出结果是?。#includevoidmain()chars=ABCD;char*p;for(p=s;ps+4;p+)coutpendl;