同变量的数据类型类似,指针也有类型。之所以指针会有类型,是为了符合对应的变量或常量数据类型。要注意,指针本身也是一种数据类型。
不同指针类型的本质在于不同的操作。这点和快捷方式是类似的。比如双击一个可执行文件(.EXE)快捷方式的操作是运行这个可执行文件,而双击一个Word文档文件(.DOC)快捷方式的操作是使用Word程序打开这个文档。类似地,一个字符型数据在内存中占用一个字节,那么读取数据就应以字符型数据读出一个字节;一个长整型数据在内存中占用四个字节,那么读取数据时就应以长整型数据读出四个字节。如果指针类型与它所指向的数据类型不匹配,就可能对数据作出错误的操作。
指针变量也是一种变量。所以在使用之前,必须先声明。声明指针变量的语句格式为:
指针的类型 *指针变量名;
其中,指针类型应该是与指针所指向的数据相符合的数据类型。比如int、char、float等等。*表示所要定义的是一个指针变量,而不是一个普通变量。指针变量名则应该遵循起变量名的一切规则。
例如:
char *cptr;//指向字符型变量的指针变量
int *iptr;//指向整型变量的指针变量
要注意,当我们要声明多个指针变量时,必须在每个指针变量名前加上*,例如:
int *iptr1,*iptr2,iptr3;//iptr1和iptr2是指向整型变量的指针变量,而iptr3是整型变量
我们已经声明了指针变量,那么我们如何获得数据在内存中的地址呢?
在C++中,用&操作符可以获取变量或常量在内存中的地址,我们称之为取地址操作符。它的使用格式是:
&变量名或常量名
既然能够获取到数据所在的地址,我们就能把这个地址交给指针了。例如:
int c=9;
int *iptr=&c;//声明指向整型变量的指针变量,并作初始化
这时,我们称指针iptr指向了变量c。在第三章我们说过,声明一个未经初始化的变量之后,它的值是无法确定的。所以如果声明了一个指针却不对它作初始化,那么它所指向的内容也是无法确定的,而这种情况是十分危险的。
没有初始化的指针变量是危险的。可是如果在声明变量之后,找不到合适的地址进行初始化,我们该怎么办呢?显然,随便找个地址对指针变量做初始化是不负责任的。
在这里,我们引入一个特殊的地址——NULL。它的意思是“空”,即指针没有指向任何东西。比如:
int *iptr=NULL;
要注意的是,C++是大小写敏感的,NULL与null是不同的。所以,在使用的时候必须要大写。
双击一个有效的快捷方式,就能够调用对应的文件,那么我们通过什么方法才能操作指针所指向的变量呢?在这里,*又出现了,它称为间接引用操作符。其作用是获取指针所指向的变量或存储空间。间接引用的指针可以作为左值。(关于左值概念请参见第三章)具体的使用格式为:
*指针变量名
下面,我们来看一段程序,实践一下如何使用指针变量:(程序8.2)
#include "iostream.h"
int main()
{
int i=3;
int *iptr=&i;
int **iptrptr=&iptr;//iptr也是变量,也能够获取它的地址
cout <<"Address of Var i=" <<iptr <<endl;//输出iptr存储的内容,即i在内存中的地址
cout <<"Data of Var i=" <<*iptr <<endl;//输出iptr所指向的变量
cout <<"Address of Pointer iptr=" <<iptrptr <<endl;//输出iptr在内存中的地址
cout <<"Address of Var i=" <<*iptrptr <<endl;//输出iptrptr所指向的变量,即iptr
*iptr=2+*iptr;//*iptr可以作左值
cout <<"Data of Var i=" <<*iptr <<endl;
return 0;
}
运行结果:
Address of Var i=0x0012FF7C
Data of Var i=3
Address of Pointer iptr=0x0012FF78
Address of Var i=0x0012FF7C
Data of Var i=5
通过运行结果,我们可以知道变量i在内存中的地址是0012FF7C(前面的0x表示这是一个十六进制的数);指针也是一种变量,在内存中也有地址;间接引用指针以后就和使用指针指向的变量一样方便。