要搞清一个指针首先必须搞清指针的四方面的内容:指针的类型,指针所指向的类型,指针的值或者叫指针所指向的内存区,还有指针本身所占据的内存区(这里只对int型进行说明,其他的类推)。
指针的类型:从语法的角度看,你只要把指针声明语句里的指针名字去掉,剩下的部分就是这个指针的类型,这是指针本身所具有的类型。
例如:
(1)int *ptr; //指针的类型是 int * 整型指针
(2)int **ptr; //指针的类型是 int ** 指针的指针
(3)int (*ptr)[3]; //指针的类型是 int(*)[3] 数组指针
(4)int *ptr[3]; //指针的类型是 int*[3] 指针数组
指针所指向的类型:
(1)int *ptr; //指针所指向的类型是 int 指向整型
(2)int **ptr; //指针所指向的的类型是 int * 指向整型指针
(3)int (*ptr)[3]; //指针所指向的的类型是 int()[3] 指向整型数组
(4)int *ptr[3];//指针所指向的类型是 int[] 指向指针数组的第一个单元
指针的值(又称指针所指向的内存区或地址):指针的值是指针本身存储的数值,这个值将被编译器当作一个地址,而不是一个一般的数值。
在32位程序里,所有类型的指针的值都是一个32位整数,因为32位程序里内存地址全都是32位长。指针所指向的内存区就是从指针的值所代表的那个内存地址开始,长度为sizeof(指针所指向的类型) 的一片内存区。以后,我们说一个指针的值是XX,就相当于说该指针指向了以为首地址的一片内存区域;我们说一个指针指向了某块内存区域,就相当于说该指针的值是这块内存区域的首地址。
指针本身所占据的内存区:指针类型本身占据的内存空间,在32位平台中,指针本身占据4个字节的长度,可以使用sizeof(指针类型)来测试下指针占据的存储空间。
以上是预备知识,接下来言归正传。
指针的指针:这个比较简单,如下代码1:
指针pni指向整型变量ni,pni的值为ni所在内存中的地址,指针的指针ppni指向一个整型指针,ppni的值为指针pni所在的存储单元的地址。
int ni=10;
int* pni=∋
int** ppni=&pni;
数组指针:顾名思义,指向数组的指针,这里一定要区分指向数组首单元的指针和数组指针的区别。如下代码2:
int narr[3];
int *p=narr;
在以上代码中,narr只是一个指代数组首地址的指针,而不是一个指向数组的指针。所以p只是一个指向数组首地址的指针。
这个例子在《指针和数组名的区别》文章有详细介绍。 数组指针的使用见下代码3:
void main()
{
int array[2][3] = {{1,2,3},{4,5,6}};//二维数组看作是两个一维数组
int (*pa)[3]; //申明一个数组指针,若(*pa)[3]中不为3则出错
//array[0]指代二维数组中{1,2,3}的首地址,那么&array[0]是数组指针型
pa = &array[0];//即(*pa)相当于array[0]。
cout<<pa[0]<<"|"<<pa[1]<<"|"<<pa[2]<<endl;
cout<<pa<<endl;
cout<<*pa<<endl;
cout<<(*pa)[0]<<"|"<<(*pa)[1]<<"|"<<(*pa)[2]<<endl;
cout<<**pa<<endl;
cout<<*(*pa+2)<<endl;
pa++;
cout<<pa[0]<<"|"<<pa[1]<<"|"<<pa[2]<<endl;
cout<<pa<<endl;
cout<<*pa<<endl;
cout<<(*pa)[0]<<"|"<<(*pa)[1]<<"|"<<(*pa)[2]<<endl;
cout<<**pa<<endl;
cout<<*(*pa+2)<<endl;
}
输出为:
0012FF68|0012FF74|0012FF80
0012FF68
0012FF68
1|2|3
1
3
0012FF74|0012FF80|0012FF8C
0012FF74
0012FF74
4|5|6
4
6
以上代码中第三行定义的pa是指向一个3维数组的数组指针。*pa就是一维数组的指针,自然可以使用(*pa)[i]的方式访问数组,而*pa+1则是(*pa)[1]这个元素的地址,所以自然得到第5,6,7行所注释的输出。经过pa++语句,由于pa是数组指针,后来pa中存放的地址应该是*pa+sizeof(array[0]),所以现在*pa就是一维数组{4,5,6}对应的首地址,同理得到第9,10,11行所注释的输出结果。
指针数组:也就是指针的数组,存放指针的数组,数组中的元素是指针。
例如:
int n1=10;
int n2=20;
int* np[2]={&n1,&n2};
cout<<*(np[0])<<endl;
cout<<*(np[1]);//输出20
上述代码的第三行定义了一个指针数组,数组中含有两个元素,分别是n1、n2的地址,np[0],np[1]就是对应的这两个地址,所以*np[0],*np[1]分别是10,20
对于指针的指针、数组指针、指针数组,我们还可以给出更为直观的定义方法:
指针的指针:
typedef int* intP;
intP* p;
数组指针:
typedef int intArray[2];
intArray* p;
指针数组:
typedef int* intPtr;
intPtr p[2];
由于一些运算符优先级不同(*的优先级比[]低),所以在适当的时候使用typedef可以有效的避免迷惑性。