指针和数组相关的一些题目---(3)

在(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”

再来看一下程序运行的结果:

以上的理解有什么问题欢迎大家指正!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章