在(2)中分析了题目3,题目4和题目5,这篇博客来分析题目6,题目7和题目8,也是最后的3道题目。
题目6.
//练习6
int main()
{
int aa[2][5] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int *ptr1 = (int*)(&aa + 1);
int *ptr2 = (int*)(*(aa + 1));
printf("%d,%d", *(ptr1 - 1), *(ptr2 - 1));
return 0;
}
我们将这个代码中的aa[2][5]数组在内存中的储存形式用图模拟出来:
现在我们来分析这个代码:
“int *ptr1 = (int*)(&aa + 1);”:
“&aa”就是aa数组整体的地址,“&aa+1”表示aa数组最后一位元素的下一位地址。再将它强转为int型指针,赋给ptr1。
“int *ptr2 = (int*)(*(aa + 1));”:
“(aa+1)”就是给aa数组的首元素地址加一,它就是aa数组的第二位元素的地址。aa数组是一个二维数组,第二位元素的地址就是它的元素6的地址。在将它强转为int型指针,赋给ptr2。
结果:所以*(ptr1-1)就是aa数组的元素10,*(ptr2-1)就是aa数组的元素5。
我们来看看程序的结果:
题目7.
//练习7
int main()
{
char *a[] = { "work", "at", "alibaba" };
char **pa = a;
pa++;
printf("%s\n", *pa);
return 0;
}
我们将这个代码中的a[]数组在内存中的储存形式用图模拟出来:
我们来分析一下代码:
“char **pa = a”:
pa是一个二级指针,它指向a这个指针数组,具体来说此时它指向a数组的首元素地址,即指向“work”字符串的指针的地址。所以“pa++;”后pa就指向指针数组的第二个元素的地址,所以“*pa”就是“at”。
我们来看一下代码运行的结果:
练习8.
//练习8
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;
}
我们将这个代码中的各个变量在内存中的储存形式用图模拟出来:
接下来我们对这个代码进行分析:
1:“**++cpp”:
其中“cpp”先与“++”结合,此时的cpp指向cp[1]。接着“++cpp”在和“**”结合,就得到了“POINT”字符串首元素的地址。
cpp的初始指向变化如图:
2:“*--*++cpp+3”:
在1的基础上,此时“cpp”与“++”先结合,指向“cp[2]”;在与“*”结合,此时得到“c[1]”,即“*++cpp”为“cp[2]”;与“--”结合,此时指针指向“ENTER”;在与“*”结合,此时得到“ENTER”首字符的地址,最后“+3”,得到了“ENTER”第四个字符的地址。
cpp的初始指向变化如图:
3:“*cpp[-2]+3”:
在“2”的基础上,“cpp[-2]”就等于“*(cpp-2)”,得到了c[3];接着在与“*”结合,得到了“FIRST”的首字符地址;在与“+3”结合得到“FIRST”的第四个字符的地址。
此次cpp的初始指向未发生变化,如图:
4:“cpp[-1][-1]+1”:
在“3”的基础上,“cpp[-1]”就等价于“*(cpp-1)”,此时得到c[2]地址;再次与“[-1]”结合等价于“*(cpp[-1])-1)”,得到“NEW”的首字符的地址;在与“-1”结合,得到“NEW”的第二个字符的地址。
cpp的初始指向未发生变化,如图:
由1,2,3,4得到结果:屏幕打印:“POINT” “ER” “ST” “EW”
再来看一下程序运行的结果:
以上的理解有什么问题欢迎大家指正!