1.sizeof(数组名),这里的数组名表示的是整个数组,计算的是整个数组的大小
2.&数组名,这里的数组名表示的是整个数组,取出的是整个数组的地址
3.除此之外,所有的数组名表示的都是首元素的地址
假设我们有如下代码:
int main(void)
{
char* c[] = { "ENTER", "NEW", "POINT", "FIRST" };
char** cp[] = { c + 3, c + 2, c + 1, c };
char*** cpp = cp;
printf("%s\n", **++cpp);
printf("%s\n", *-- * ++cpp + 3);
printf("%s\n", *cpp[-2] + 3);
printf("%s\n", cpp[-1][-1] + 1);
return 0;
}
那么其输出结果为如下所示:
要理解为什么输出的形式是这样的,我们就必须要理解这两个数组和一个指针指向的内容
首先看上面三个指针,c是一个char*类型的指针数组,其内容为char*类型的四个字符串;而cp是一个二级指针数组,其内部存储的是四个地址;cpp则是一个三级字符指针,指向的是cp数组的数组地址。
而其指向关系如图所示:
理解了两个数组和一个指针的含义,就可以看下面的三个打印
一、
我们可以看到,在这个打印中,首先,++优先级较高,cpp是一个指向cp数组的指针,而由于数组的地址其实就是首元素的地址,因此,cpp实际上指向了cp数组中c + 3这一元素。++cpp,cpp自身+1,此时cpp指向c+2这一元素。然后在++cpp的前方有**,意思是解引用两次。第一次对cpp解引用会得到cp数组中c+2这一元素,而第二次解引用因为c+2这一元素是一个指针,指向的c数组中“POINT”这一元素,由此可知,在对++cpp两次解引用后打印得到的是“POINT”这一字符串。
二、
这这个打印中,从优先级上来看,++的优先级更高,因此首先++cpp。而在上一个打印中cpp已经++了一次,因此在进行++cpp后,cpp指向的c+1这一元素。随后可以看到在++cpp前方有一个*,对++cpp解引用后就拿到了cp数组中c+1这一元素的内容。然后可以看到*++cpp前方有一个--,因为此时已经对cpp解引用过一次,因此此时--的对象是c+1这一元素。c+1进行--操作后得到的是c,而c是指向“ENTER”这一元素的一个二级指针,因此解引用后得到的就是“ENTER”这一字符串,而指针则是指向该字符串中首字符的元素的地址,即“E”的地址。此时再进行+3,因为c是一个一级指针数组,而cpp两次解引用后得到了“E”的地址,此时+3是在“E”这一字符地址上+3,最终指向的就是“ENTER”中第二个"E”的地址,对其打印后就会得到“ER”
三、
在这个打印中,可以看到是对出cpp[-2]进行解引用,而这个cpp[-2]可以看做*(cpp - 2),但是在前面的打印中可以知道cpp此时指向的是cp数组中的第三个元素,因此*(cpp - 2)所得到的就是cp数组中的第一个元素c+3的值,而c+3本身是一个二级指针,对其解引用后得到c数组中的“FIRST”这一字符串,此时指针指向的首字符“F”的地址,+3后得到“S”的地址,打印后结果为“ST”
四、
对这一个打印,可以将出cpp[-1][-1]看为*(*(cpp -1)- 1),因为cpp此时指向的cp数组中的第三个元素的地址,cpp -1后指向的是cp数组中的第二个元素的地址,解引用得到cp数组中的第二个元素c+2,此时再对c+2进行-1操作,得到c+1,。因为c+1本身是一个指针,指向c数组中的“NEW”,此时解引用后得到该字符串首元素“N”的地址,在对这一地址+1后得到“E”,此时打印所得到的就是“EW”