//题目:
int main()
{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,cp,cpp之间的关系画出来:

c[ ]数组里放着分别是ENTER,NEW,POINT,FIRST的首字母的地址,而cp里分别放着c+3,c+2
c+1,c,这里的c代表着c数组首元素的地址,cpp里呢存放着cp数组的首元素地址。
我们一个一个分析:
1.
printf("%s\n", **++cpp);
cpp这个指针先+1,表示什么意思呢?cpp这个指针指向的是cp的元素的地址,cpp+1也就是cp元素的地址要+1,所以cpp指向的方向就改变了,然后再解引用找到圆圈1,圆圈1就是右边的方块,而再解引用,就是访问方块里面的圆圈2了,得到圆圈2,圆圈2就是POINT首字母的地址,所以打印的话就会打印出POINT。

2.
还有自增++1或者自减–,都会对变量永久性改变,所以上面的的自增仍然有效。
printf("%s\n", *-- * ++cpp + 3);
先对cpp自增+1,然后解引用,再自减1,再解引用,最后+3.
从上图可以看出,cpp先指向cp的第二个元素的地址,这里自增+1,应该变成指向第三个元素的地址了,然后解引用找到c+1这个地址,再自减,所以c+1变成了c,所以cp这个数组的c+1指向了c,然后解引用找到ENTER的首字母地址,最后+3,就变成E字母的地址了,所以打印出来应该是ER。

3.
printf("%s\n", *cpp[-2] + 3);
cpp[-2]表示什么意思呢?它可以简化成 *(cpp-2),所以这个表达式就是
**(cpp-2)+3. cpp-2,表示cpp指向的c数组的元素的地址要减2,然后解引用找到这个指针保护的地址再解引用最好+3.

4.
上面那个减2可不是永久性的改变喔,只是适用于上面,因为2不是自增和自减,只是-2,cpp的指向并没有改变所以cpp的指向还是解答2中的形式。
printf("%s\n", cpp[-1][-1] + 1);
这个代码可以简化成
*( *(cpp-1)-1)+1
cpp-1使cpp指向c+2,解引用找到红色方块的地址,然后又-1,方块的地址要变成上面的方块的地址了然后解引用,找到NEW的首字母地址,再+1,变成E的地址,最好打印出来应该为EW。
5.
结果:

总结: