char ****p

char **p;
这是啥意思,咱们需要复读机,按行分,跟着我读,记得从右向左读:
p 这是一个存储空间,申请空间的名称为p,存放的是一个指针,这个指针指向一个空间,哪个?下面这个。 (打断下,这里不需要你跟读,我说的是p,不是char *p;)

* *p 这是一个存储空间,存放的是一个指针,这个指针指向一个空间,哪个?下面这个。 
* **p 这是一个存储空间,存放的是一个指针,这个指针指向一个空间,哪个?下面这个。 
* ***p 这是一个存储空间,存放的是一个指针,这个指针指向一个空间,哪个?下面这个。

char ,这个存储空间大家就不用读了吧。

别怀疑我排版有问题。我可不是混行数的。但注意,只有第一行有 “申请空间的名称为p”。因此这里你需要确保了解2个事实。 
1、char ****p,别数有多少个*就认为这有多少空间。实际只有一个空间,位宽是指针类型,这个空间的名字在代码和编译器看到的,就是p。 
2、存储空间里的内容指向哪并不重要,重要的是指向的空间对应的类型。此处的类型有两层含义,一、是“是否是指针”,二、最终指向的空间是什么类型。 
关于第二点,你可以如此想一下,如同俄罗斯的套娃,一层层的套,总算最终有个娃了,但至少每层模样相同,外面是美女,里面最终的娃也得是一样的美女,不能外面是关羽,里面是项羽。 
为什么要这样,编译器在最终指向实际类型空间时需要检测类型宽度。下面说说怎么利用p。为了不绕口令,我们用3级指针,别搞4级指针了