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