从数组开始
假设我们有一个int arr[]={}
那么我们可以使用arr[1]
来获取第2个元素
其本质为*(arr+1)
即对代表了数组首元素地址的a
进行偏移,并解引用。
指针数组!
那么接下来我们来到了一个int *p[3]
,对,这是一个有三个指针作为元素的数组。p
指向了数组首元素的地址。
如果我们要获取第一个指针元素,可以使用p[0]
,这样我们得到了一个int*
那么要获取这个元素,就要去解引用,即*(p[0])
同时,如上文所说,[]
操作符本身可以解引用,虽然p[0]
作为一个int*
不是数组,但是他是指针,即我们依然可以对其偏移并解引用。所以p[0][0]
也就等于*(p[0])
上强度!
理解了[]
的偏移+解引用性质后,我们给出了以下的代码:
int a=12, b=23, c=66;
int* p[3] = { &a,&b,&c };
int** pp = p; //pp是指向指针的指针
定义指针变量的时候,int * p = &a
代表p指向a的地址。但是上述代码没有&p
因此,pp
并非是一个指向数组的指针,而是一个指向p
代表的地址(即元素首地址)的指针,即
int ** pp = &p[0]
p等同于数组元素首地址是编译器在表达式中的处理,并非p就是首地址。
使用*pp
即对pp
解引用,得到了int*
即p
所以**pp
就等同于*(*pp)
等同于*(*&p[0])
,即p
数组第一个元素的具体的数值。
如果是&p呢?
如果和上述所说的一样,我们有了一个pp2
int*(* pp2)[3] = &p;
那么pp2[0]
本质就是pp2
解引用就是让我们得到了数组p
,但是数组p
是指针数组,于是我们需要p[0][0]
才能获取到具体数值。所以获取具体数据即pp2[0][0][0]