第六章指针引用和动态空间管理

整理文档很辛苦,赏杯茶钱您下走!

免费阅读已结束,点击下载阅读编辑剩下 ...

阅读已结束,您可以下载文档离线阅读编辑

资源描述

1第六章指针、引用和动态空间管理6.1指针的概念和指针变量的定义指针是一种十分重要的构造数据类型,C++程序中常常使用指针,使用指针的好处是:更适合表达某些算法,使用指针可以写出更为紧凑和有效的程序。要学好C++必须学好指针。6.1.1指针的概念指针是一种数据类型。指针-就是指针类型变量,即指针变量。指针变量常常直接简称指针。与一般变量的不同点:它存放的不是数据的值,而是另一个变量的地址。就是说指针变量:用来存放另一变量的内存地址的变量。每个变量和函数声明后,编译器就会为它们在内存中开辟一块存储区域,这块区域的地址就是变量的地址。这块区域中存放的数据值(内容)就是变量的值。对变量的访问(引用),实质就是对变量存储空间的内容(数据值)进行访问。这样我可以用另一种方法来访问变量内容,即不通过变量名,而是通过变量在内存中的地址进行访问。这种访问方式就是指针访问。6.1.2指针的定义和初始化同一般变量一样,先定义后使用。定义时要指明指针的类型,并在指针名前加修饰符*。格式:类型修饰符*指针名或者类型修饰符*指针名2*只是类型修饰符、不是变量名的一部分。如语句:int*x_ptr;或int*x_ptr;定义了一个指向int型变量的指针(变量)x_ptr。而char*x_ptr;或char*x_ptr;定义了一个指向char型变量的指针(变量)x_ptr。注意:语句int*x,y;不是定义了两个int型指针,而是定义了一个int型指针和一个int型变量。int*x,*y;指针定义后,并不具体地指向某个变量,而只是确定了类型。可以对指针进行初始化,让它指向某个具体的变量。这通常用到运算符’’&’’。它是取地址运算符。用在操作数的前面,表示取操作数的内存地址。操作数可以:一般的变量、数组元素、结构成员等。如:floatsalary;float*salary_ptr=&salary;//将指针salary_ptr初始化为变量salary的内存地址值,也即指向了具体的salary。6.1.3常值指针可以用const把一个指针定义为常值指针。常值有两种含义:一种是指针所指向的数据为常值,这时须将const放在*号的前面。如constchar*s=“Hello!”;//charconst*s=“Hello!”;//charconst*s;s=“Hello!”//s是一个指针变量,它指向一个字符串常量。不能用该指针来改变其所3指向的内容,指针s本身可以改变的。如s=“Hi”//正确,*s=‘Y’//错另一种:指针本身是常值,须将const放在*的后面。如:char*consts=”Hello!”;//s是一个指针常量,它指向一个字符串变量。指针的内容可变,指针本身不可变。对于指针常量,必须在定义时对其初始化。与前相反。如s=“Hi”//错,*s=‘Y’//正确也可以是上述两者的综合。两者都不能改变。6.2指针的基本操作6.2.1指针赋值:操作符=指针定义时可以对它进行初始化。如:floatsalary;float*salary_ptr=&salary;也可以声明指针变量后赋值:如:inta=-8978;int*p;p=&a//p被赋值为变量a的地址。同类型指针可以互相赋值。如:doublea;double*x=&a,*y;y=x//x,y指向同一个变量a。intcount=78,*c_ptr=&count;c_ptr=x;//错,不同类型指针特殊指针-空指针。值为零的指针C++函数库中都将空指针定义为名字NULL。因此将指针赋值为NULL即赋值为零。如:x=NULL;即为;x=0用修饰符void修饰的指针变量,为void指针。任何类型的指针可赋给void4指针,但反过来不行。6.2.2取值的地址:操作符&floatsalary;float*salary_ptr=&salary;//salary_ptr指向salary。6.2.3间接访问(取内容运算符)操作符*用在指针变量的前面,表示取指针所指向的存储单元的值,也即取指针所指变量的值。如:inta=90;inta_ptr=&a;intx;x=*a_ptr;//把a_ptr所指的存储区域的内容,即变量a的值赋给x,x等于90。而*a_ptr=98;//将98填入a_ptr所指的存储区域,即a的值被填为98。同理*a_ptr=*a_ptr+1;//a_ptr所指的存储区域的值加1,即a的值被加了1,与a=a+1效果一样。注意:声明语句中和赋值中*的含义是不同的。声明语句中:*是指针类型修饰符,用来说明变量是指针变量;赋值语句中*是取内容运算,用来取指针变量的内容。&与*是互逆的操作,这两个操作符在一起,其作用互相抵消。如;*&r=3;与r=3;效果一样。6.2.4判断——指针是否为空指针:操作符==(等于)!=(不等于)(书所示了解)56.2.5计算两地址间数据单元的个数指针存放的是内存地址,关于指针的运算就是关于地址的运算。地址是无符号整数值。同类型指针相加,其结果是一个整数,表是两个地址之间可容纳的相应类型数据的个数。例子如书所示。2.6.6指针移动1.指针与整数相加或相减(移动n个单位)。指针与整数进行的加、减运算,代表着指针在内存空间上、下移动。加1表示指向当前所指单元的上一单元。减1表示指向当前所指单元的下一单元。具体的上移或下移的字节数与其类型相关。如:字长为32的计算机中,一个int型数据占4个字节,如果有inta=78;int*x=&a;//x初始化为指向变量a。在语句x=x+1(x+=1);执行后,x中存放的地址被加了4,指向变量a的下一个整数。同理,语句x=x-1(x-=1);执行后,x指向了上一个整数。思考:假定一个double型数据占8个字节,x=x-3;x=x+3;又会怎么样?2.移动一个单位在指针使用加1或减1时,也可以使用C++的增1运算符++和减1运算符――。当++和――与*同时作用指针时,与普通变量一样注意运算的顺序。例如:x=*p++;相当于x=*(p++)//即先将地址加1,再取地址中的数据的6类型转换。又如:x=*++p;相当于x=*(++p)//含义同前而x=++*p;相当于x=++(*p)//表示先取p所指向的单元内的数据值,再将数据值加1后赋给x。6.2.7指针表达式的副作用(书所示)6.2.8指针类型的强制转换任何类型的指针可以强制转换,格式:(类型修饰府*)指针表达式如(书所示):6.2.9指针操作符的综合运用(书所示)6.3指针与数组C++中,指针与数组有着密切的关系。数组名本身就是一个指针(常量指针),对数组元素的引用即可以采用下标的形式,又可以采用指针形式;反过来,指针也可以当作数组来使用。6.3.1一维数组元素的指针访问方式如:inta[10]={3,56,287,78,43,65,4,37,85,1276};//定义并初始化了一个一维数组,它的10个元素用下标形式分别表示:a[0],a[1],a[2]-------a[9]7若使用指针形式来表示a的元素时,a可以当作一个int型的指针变量,存放着数组的首地址。则a的元素可以表示为:*(a+0)或*a,*(a+1),*(a+2)-----------,*(a+9)若要将a[4]赋值为-59,既可用语句;a[4]=-59,*(a+4)=-59;两者等效。在C++中,任何一个数组的名字都可以作为一个常量指针来使用,常量指针是指它的值不能被改变。数组名作为一个常量指针,存放的是这个数组在内存中所占区域的起始地址,也即第一个元素的地址。这样数组元素皆可以使用指针形式来表示。设数组名为a,其元素a[i]可以用指针形式表示为:*(a+i)。例子:#includeiostream.hvoidmain(){inta[5]={1,2,3,4,5};couta[0]a[1]a[2]a[3]a[4]endl;//数组形式coutaendl;//输出数组首地址cout*a*(a+1)*(a+2)*(a+3)*(a+4)endl;//指针形式}//使用下标的形式或指针形式来应用数组元素,其效果是一样的。6.3.2多维数组元素的指针访问方式。二维数组用指针的形式表示的方法与一维数组类似。假设有inta[3][4];//三行四列的数组其元素下标形式为:a[0][0],a[0][1],------,a[2][2],a[2][3]。换个角度,a又可以看作一个有3个元素的一维数组,每行一个元素,每个元素又8都是一个具有4个元素的一维数组。即:a[0]a[1]a[2]a的3个行元素可用指针表示为:*(a+0),*(a+1),*a(a+2)以第一行元素*(a+0)为例,其包含的4个元素又可以分别表示如下:*(*(a+0)+0),*(*(a+0)+1),*(*(a+0)+2),*(*(a+0)+3)//其余依次类推。由此可知二维数组a的任一个元素a[i][j]的指针形式:*(*(a+i)+j)也可以只将行、列下标中的一个元素用指针形式表示,另一个用下标形式表示。二维数组a的任一个元素a[i][j]也可以用如下形式表示:*(a[i]+j)或(*(a+i))[j]此外,由于无论一维还是多维数组,在内存中都以一维的形式存放的,可以按存放的顺序来使用指针。例如:上述数组,其任一个元素a[i][j]也可以用:*(a+i*4+j)表示。//乘以4因为第二维的大小为4。例子(书所示):6.3.3关于“指向数组的指针”数组名可以作为常量指针使用。常量指针的值是不能改变的,以任何形式对它进行赋值或修改都是不允许的。例如:floattotal[4]={3.56,-45.52,90,127.39};9floatx,y;x=*total;total=total+1//非法;y=*total;上面,将数组名total的值加1,这是不合法的。这时可以用一个变量指针来代替常量指针,让它指向该数组,而它的值可以被修改。Float*p=total;//将p初始化为指向数组totalx=*p;p=p+1;//合法y=*pp是一个变量指针,完全可以对它进行加1操作。其中,让p指向total也可以用:float*p=&total[0];//将p初始化为total[0]的地址,也即数组的首地址。指向数组的指针可以被修改,而数组名是常量指针,其值不能被修改,只能固定的指向某一数组。指针的形式来引用数组,指针也可以直接当成数组来用。例子:当成数组来用的指针#includeiostream.hvoidmain(){intx[3]={4,5,6};int*p=x;//让指针p直线数组xcoutx[0]x[1]x[2];coutp[0]p[1]p[2]endl;}//先将指针p初始化为指向数组x,将p作为数组来使用,它的3个元素p[0],p[1],p[2]实际上就是*p,*(p+1),*(p+2),即指针*(p+i)可以使用下标形式p[i]。输出为456456例子[指向数组的指针的另一个例子]10#includeiostream.hvoidmain(){charstr1[]=“What’sthat?”;charstr2[]=“It’sabook。”;char*ptr;coutstr1endl;coutstr2endl;ptr=strl;//让ptr指向str1coutptrendl;ptr=str2;//让ptr指向str2coutptrendl;}//程序中ptr是指向字符串的指针,存放的是字符串的首地址,而不是字符串本身,str1、str2也是字符串的指针,但它们是常量指针。输出:What’sthat?What’sthat?It’sabook。It’sabook”。6.3.4字符指针与字符串数组名就是指针,任何指向字符型数组第1个元素的指针都可以代表存储字于该处的字符串。(书所示)。6.3.5指针数组与命令行参数数组是一批同类型变量的有序集合,同

1 / 17
下载文档,编辑使用

©2015-2020 m.777doc.com 三七文档.

备案号:鲁ICP备2024069028号-1 客服联系 QQ:2149211541

×
保存成功