先上题目:
#include <stdio.h>
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;
}
紧接着,我们初始数据的结构图:
上图是是char* c,char** cp和char*** cpp的关系图,接下来,我们根据输出的要求逐一进行变换。
第一个**++cpp;
printf("%s\n", **++cpp);
表示的是三级指针cpp先++再使用,即将char*** cpp的位置从char** cp 中的c+3的起始部分,移动到c+2的起始部分,然后进行一步解引用,得到第三个char*,再进行解引用得到POINT的起始位置,接下来根据%s打印该字符串,则最后的输出值是POINT。
第二个*-- * ++cpp + 3;
printf("%s\n", *-- * ++cpp + 3);
此时要注意,由于程序已经走完第一个输出值,故该数据结构图应该是上图(绿色箭头),
那么我们根据上图来进行分析;
首先根据优先级,++的优先级最高,然后是--,最后是+。
++cpp,表示先++再使用,即char*** cpp的位置从char** cp 中的c+2的起始部分,移动到c+1的起始部分,然后进行解引用,得到第二个char*,再进行--,此时的--是对于c+1进行,所以此时c+1变为c,然后指向的位置从第二个char*变为第一个char*,再解引用得到ENTER地址的起始位置,+3跳过三个元素之后的地址即E的地址,然后再以字符串的形式输出,得到了ER。
第三个*cpp[-2] + 3;
printf("%s\n", *cpp[-2] + 3);
还是优先级的问题,[]的最高,然后是+;
首先,cpp[-2]等价于*(cpp+(-2)),cpp-2表示char*** cpp的位置从char** cp 中的c的起始部分,移动到c+3的起始部分,再进行解引用,得到第四个char*,然后再进行解引用,得到FIRST地址的起始位置,+3表示起始地址向后移动3个元素,即ST的起始位置,最后以字符串输出,结果为ST。
第四个cpp[-1][-1] + 1;
那么这里先题一点:通过赋值才可以改变char** cp每一个元素的值,而类似于第三点所提到的cpp[-2]只是通过这种方式改变路径,并没有对其进行赋值,所以此时的char*** cpp的初始位置还是char** cp的第三个元素。
我们继续分析,cpp[-1][-1]等价于*(*(cpp+(-1))+(-1)),即先对cpp进行-1,则cpp表示的地址从c移动到c+2,然后再进行解引用,得到char* c 中的第三个char*,然后再进行-1,则从第三个char*转移到第二个char*,然后再进行解引用,到NEW的起始位置,+1表示跳过一个元素之后的地址,即EW的起始地址,最后输出得到EW。
感谢大家的观看。