自从学习了指针之后,就被指针的指向和解引用所困扰,我认为理解多级指针的使用逻辑更能加深我对指针的理解。
首先,先从比较简单的开始:
int main() {
int matrix[3]={1,2,3};
int* p=matrix;
p++;
printf("%d",*p);
return 0;
}
这里将数组首元素的地址存入指针p中,因为数组中元素的地址是连续的,所以p++后,p指向第二个元素,解引用后访问到2进行打印。
int main() {
int a=1,b=2,c=3;
int *matrix[3]={&a,&b,&c};
int** p=matrix;
p++;
printf("%d\n",**p);
printf("%d\n",*p[0]);
printf("%d\n",p[0][0]);
return 0;
}
现在拓展一下,matrix现在是存放指针的指针数组,也是第一个指针的地址,所以可以由二级指针p存放。同样指针数组的元素存放的地址是连续的,所以p++,相当于指向第二个元素(一级指针)的地址,如果这样理解不了,还可以看p指向的类型是int * 类型,所以+1一次跳过一个int * 类型的指针,指向matrix的第二个元素。
所以解引用找到matrix的第二个元素,在解引用找到b的值2打印。这里还有一点想要说,也是很重要帮助我们理解的一点:*(p+1) = p[1] ,从代码中也可以看出来,三个打印结果是一样的。
#include<stdio.h>
int main(){
char* p1[]={"FIRST","SECOND","THIRD","FORTH"};
char** p2[]={p1+3,p1+2,p1+1,p1};
char*** p3=p2;
printf("%s\n",**++p3);
printf("%s\n",*--*++p3+3);
printf("%s\n",*p3[-2]+3);
printf("%s\n",p3[-1][-1]+1);
return 0;
}
现在就可以来尝试这道比较绕的题了,首先画一下图,帮助我们理解指针的指向。
1.字符串也是char * 类型,存储第一个字符的地址,指向第一个字符。
2.以%s的形式打印是从传入的地址处开始打印,直到遇到‘/0’。
3.三级指针解引用得到二级指针,二级指针解引用得到一级指针。
4.数组名也是首元素的地址,所以如果是一级指针数组,那么数组名就是二级指针(是一级指针的地址(指针)),同理,二级指针数组数组名就是三级指针。
第一个**++p3,p3先++再解引用,p3存放的是p2数组的首元素地址,p3+1,指向p2数组的第二个元素(p2[1]),解引用得到p2第二个元素(从上往下数),再解引用得到p1的第三个元素,这个元素是字符串类型(也是char*类型),以%s的类型打印,打印出“THIRD”。
第二个*--*++p3+3,因为刚才p3已经++过了,所以现在p3指向的是p2第二个元素,现在p3再++,指向的的是p2的第三个元素(p2[2]),解引用得到p2的第三个元素,p2的第三个元素指向的是p1的第二个元素,再 --,指向p1的第一个元素,再解引用的得到的是p1的第一个元素,p1[1]是“FIRST”,也是‘F’的地址,地址+3,就是‘S’的地址,以%s形式打印,就是“ST”。
第三个和第二个很像,*p3[-2]+3,刚才说过,*(p+1) = p[1],所以*(p-2) = p[-2],得到**(p3-2)+3,第一个和第二个都让p3++,现在(p3-2 )表示p3又重新指向p2的第一个元素p2[0],解引用后找到p2[0],再次解引用后,得到p1的最后一个元素(p1[3]),p1[3]指向的是“FORTH”的首字符,+3后指向的是‘T’,以%s的形式打印,得到“TH”。
第四个也类似,不过要注意第三次只是访问p3-2打印,并没有改变p3的指向,现在p3仍然是指向p2的第三个元素p2[2],p3[-1][-1]+1相当于*(*(p3-1)-1)+1,p3-1指向的是p2数组的第二个元素p2[1],解引用找到p2[1],p2[1]指向的是p1的第三个元素,再-1指向p1的第二个元素p1[1],再解引用找到p1[1],p1[1]指向的是“SECOND”的首字符,+1指向‘E’,以%s的形式打印得到“ECOND”。
最后附上运行结果的照片,第一次画图讲解指针,如有错误欢迎讨论,希望文章对你有所帮助。