VC++程序设计 -第八章 指针和引用

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

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

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

资源描述

第八章指针和引用本章是本书的重点之一,指针的使用是比较复杂的,但又是十分重要的。正确灵活地应用指针,可有效地使用各种复杂的数据结构;能动态地分配内存空间;能更有效更方便地使用数组和字符串;能编写通用的程序等。正确熟练地掌握指针的应用,设计的程序可以简洁、高效。但是,若程序中不正确地使用指针,则容易导致程序运行时的错误,或导致系统的崩溃。在学习本章时,一定要理解指针的本质,并能正确应用指针。对于初学者,指针的概念和用法不容易掌握,学习时要认真领会其特点和本质。8.1指针及指针变量8.1.1指针的概念当我们说明一个变量时,编译程序要为这个变量分配一个连续的内存(主存)单元。为了区分不同的内存单元,必须给每一个内存单元指定一个唯一的编号,这个编号称为内存单元的地址。目前,多数计算机是以一个字节(八个二进位)作为一个昀小的内存单元。内存单元的地址类同于一个旅馆中的房间号码,存放在内存单元中的数据类同于住在某一房间号码中的旅客。当知道一个旅客住在一个旅馆时,只要知道其房间号码,就能找到这个旅客。同样地,只要知道了为变量分配的内存单元的地址,就可以使用或改变这个变量的值。当然,每一个房间的“房间号码”(内存单元的地址)是唯一的,是不可改变的;而在房间内的“旅客”(变量的值)是可以经常改变的。设有说明语句:charc1=’a’;floatx=50.5;编译程序在编译时,或在程序的执行期间要为变量c1和x分配内存单元,设分配的内存单元分别为20001和20004,如图8.1所示。20001:20004:图8.1变量的地址与变量的值图中的20001和20004为地址,为变量c1分配了一个字节的内存单元,而为变量x分配四个字节的内存单元。变量c1的值a存放在20001的内存单元中,而变量x的值50.5存放在以20004开始的四个连续的字节(内存单元)中。在变量c1和x的生存期内,为其分配的内存单元地址是不变的,当改变变量的值时,存放在这二个地址中的值随之变化。注意,应该区分变量的地址和变量的值的概念,在编译或执行期间为每一个变量分配的内存单元的编号(地址)称为变量的地址;而该内存单元中的内容称为变量的值。变量的地址称为变量的指针,简称为指针,即指针是一个内存单元的a50.5地址。当定义(说明)一个变量时,其值总是用来存放一个内存单元的地址(指针)时,称这种变量为指针变量。换言之,一个指针变量的值一定是另一个变量的地址。引入指针变量的目的是提供一种对变量的值进行间接访问的手段;根据指针值,可以使用或修改该指针所指向的内存单元中的值。8.1.2指针变量的说明指针变量与其它类型的变量一样,必须先说明后使用,说明指针变量的一般格式为:《存储类型》类型*变量名1《,*变量名2,......》;其中存储类型是可任选的;变量名前的星号*指明所说明的变量为指针变量;而类型则指出指针变量所指向的数据类型,即指针所指向的内存单元中存放的数据值的类型。例如:int*p1,*p2,i,j;float*p3,*p4,x,y;char*pc,c;说明了五个指针变量p1,p2,p3,p4和pc,它们分别为整型、实型和字符型指针变量。有关指针变量,说明以下几点:1)在变量说明语句中,变量名前的星号*具有特定的意义,它表示这种变量是指针型变量。如例中的p1,p2为指向整型数据的指针型变量;p3,p4为指向实型数据的指针型变量。2)指针型变量的值只能是某一个变量地址(起始地址),在说明指针变量时,通常其值是不确定的(静态存储类型、文件作用域类型的变量除外)。只有对指针变量赋值后,才能使用它。3)编译程序也要为指针变量分配内存单元,因为指针变量的值是一个地址,其取值范围是不变的,通常用四个字节来表示地址值;所以,为不同类型的指针变量所分配的内存单元的大小是相同的。对于上例中的变量说明,为指针变量p1,p2,p3,p4和pc各分配四个字节大小的内存空间。4)定义指针类型变量时,其类型定义了指针变量所指向的数据类型,这类型确定了数据占用的存储空间的大小。如,p1,p2所指向的数据为整型,故占用四个字节的空间,而pc所指向的数据为字符型,它占用一个字节的存储空间。5)在说明指针变量的同时也可以对它进行初始化。通常是用与指针变量同类型变量的指针来进行初始化。如:intj,*p=&j;说明了整型变量j和整型指针变量p,同时将变量p的初值置为变量j的起始地址。运算符“&”称为地址运算符,这是一个一元运算符,它的运算结果是取其操作数的地址值。该运算符的操作数只能是一个变量或对象。在程序中,要得到一个变量的地址时,可用这运算符来获得。在C++中,允许将一个整型常数经强制类型转换后,来初始化指针变量。如:int*pp=(int*)0x5600;则将指针变量pp的初值置为0x5600,即使pp指向地址为0x5600的内存单元。这种初始化方法,只有在设计系统程序或对计算机硬件方面非常清楚内存单元的作用时,才是有意义的。否则,这种初始化的物理意义不仅不明确,而且还可能产生极为严重的后果。因此,对于初学者来说,不能使用这种方法来对指针变量初始化。8.1.3指针可执行的运算指针的运算(操作)只有赋值运算、关系运算和算术运算三种。8.1.3.1指针的赋值运算指针的赋值运算是将一个地址值赋给一个指针变量。这种赋值有三种情况:1、可以将与指针变量同类型的任一变量的地址赋给指针变量。例8.1指针的赋值运算和算术运算。#includeiostream.hvoidmain(void){inta1=1,a2=2;int*p1,*p2,*p3;float*fp1,*fp2;floatb1=23.5,b2=55.6;p1=&a1;//A将变量a的地址赋给p1p2=p1;//B同类型的指针变量之间的赋值p3=&a2;fp1=&b1;//Cfp2=&b2;cout*p1=*p1*p2=*p2*p3=*p3\n;//Fcoutp1=p1p3=p3'\n';cout*fp1=*fp1*fp2=*fp2'\n';//G}执行程序后的输出为:*p1=1*p2=1*p3=2p1=0x0065FDDCp3=0x0065FDD8*fp1=23.5*fp2=55.6程序中的A行是将整型变量a的地址赋给指针变量p1,经这种赋值后,称指针变量p1指向变量a1。当定义了一个指针变量,并对其赋初值后,就可以在程序中访问该指针变量。对指针变量的访问一般有二种形式:一是访问指针变量的值;二是访问指针变量所指向的内存单元中的数据。第二种访问形式称为访问指针的内容。对指针值的访问通常是将一个指针变量的值赋给另一个指针变量或者是进行指针的运算。通常,程序设计者并不并心指针变量的具体值,而只关心它指向哪一个变量。上例中的B行是将指针变量p1的值赋给指针变量p2,这是同类型的指针变量之间的赋值。这种赋值,使得p1和p2都指向变量a,在图8.2中给出了指针的指向关系。a:p1:p2:图8.2二个指针变量指向同一个变量要访问指针变量所指向的内容时,要用到运算符“*”,该运算符称为取内容运算符,它是一个一元运算符,要求一个指针作为它的操作数。该运算符的运算结果为取其操作数所指向的内存单元的值(变量值)。如上例中的F行,*p1表示取出p1所指向的内容,即值为1。又如:int*ip1,*ip2,i=100,j;ip1=&i;ip2=&j;*ip2=*ip1+200;//将300赋给ip2所指向的内存单元当指针运算符出现在赋值运算符的左边时,表示将计算结果赋给指针变量所指向的变量。因ip2指向变量j,经以上的赋值运算后,j的值为300。2、在C++语言中可以将0赋给任一指针变量,其含义是初始化指针变量,使其值为“空”。实际上是告诉系统,指针值为0的指针变量不指向任一内存单元,即不指向任一变量。如程序:#includeiostream.hvoidmain(void){int*pt;*pt=0;*pt=100;//Acout*pt’\n’;}这程序能正确编译和连接,在执行程序时,当执行到A行时,系统提示“该程序执行了非法的操作”,并终止程序的执行。因pt不指向任一内存单元,当然就不允许向pt所指向的内存单元赋值。类同于其它类型的变量,当被说明为静态存储类型的指针变量或全局的指针变量时,其缺省的初值为0。C++中允许将一个整型常数经强制类型转换后赋给一个指针变量。如:float*fpp;fpp=(float*)5000;表示将5000作为一个地址值赋给指针变量fpp。因为一般的程序设计者并不知道每一个存储单元的用途,这种赋值不但通常没有意义,而且是非常危险的,程序执行时,有可能破坏系统,造成系统不能正常运行。应当强调指出的是,向一个未初始化的指针变量所指向的内容赋值是极其危险的,并且是不允许的。如以下的程序:#includeiostream.hvoidmain(void)1{int*pp;cout输入一个整数:;cin*pp;cout*pp'\n';}该程序可以被编译和连接,当执行时输入100,则输出的值也是100。似乎程序是正确的,实际上程序中存在着潜伏的危险。因指针变量pp是一个局部变量,编译程序为pp分配了一个存储空间,并不对其作任何初始化工作,pp的值是一个随机值。该值所表示的内存单元可能是没有用到的空闲空间;但是,若该值所表示的内存单元是一个系统正在使用的关键内存单元,把数据写入这内存单元,轻者导致程序不能正确执行,重者导致系统出错或系统崩溃。对于初学者尤其要注意,在程序中绝对不允许出现类似情况。3、同类型的指针变量之间可以相互赋值,而不同类型的指针变量之间的赋值经强制类型转换后尽管是允许的,但通常是没有意义的。如程序:#includeiostream.hvoidmain(void){inti=100,*p1;floatx=2.5,*p3;p1=&i;cout*p1=*p1\n;p3=&x;cout*p3=*p3\n;//Ap1=(int*)p3;//Bcout*p1=*p1\n;//C}执行程序后的输出结果为:*p1=100*p3=2.5*p1=1075838976显然昀后一行的输出结果是错误的。A行中取p3所指向的数据时,是按实数来取的,能输出正确的结果2.5;经B行赋值后,尽管p1和p3的值相同,但C行中取p1所指向的数据时,是按整数来取的,所以输出的值不是2.5。注意,由于地址的取值范围是相同的,所以,当说明不同类型的指针变量时,编译程序为指针变量所分配的存储空间的大小是相同的,目前多数计算机上大小均为四个字节。如:char*pc1;int*pi1;double*pd1;系统分别为指针变量pc1,pi1和pd1各分配四个字节的内存空间。8.1.3.2指针的算术运算可以对指针进行算术运算,但在实际使用中主要对指针进行加或减的运算。加减运算又可以分为二种:一是对指针变量的++或--操作,二是指针变量值加或减一个整型常数。1、指针型变量可以执行++或--操作,其含义并不是指针变量的值进行加1或减1的操作;而是使指针变量指向下一个或上一个元素。如:指针变量++;计算机内部是按下式计算的:指针变量=指针变量+sizeof(指针变量类型)又如:指针变量--计算机内部是按下式计算的:指针变量=指针变量-sizeof(指针变量类型)例8.2指针变量的++和—运算。#includeiostream.hvoidmain(void){inta[10]={100,200,300,400,500};inti=10,j=20,*p1=&j,*p2=&a[0];charc1[5]=abcd,*pc1=&c1[0];cout*p1=*p1'\t'p1=(int)p1'\n';p1++;cout*p1=*p1'\t'p1=(int)p1'\n';c

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

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

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

×
保存成功