一道指针题目的解法

#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[]表明c是一个指针数组,存放的是那些字符串首元素的地址,cp还是一个指针数组(或者更准确地说是二级指针数组?不过这不重要),里面存放的是c的各元素地址,cpp是一个指针变量,指向cp数组的首元素。为了方便讲解和理解,我用甲乙丙丁和ABCD来代表cp和c的各元素的地址。

好的基本的介绍做完了,我们就来看看题目吧。

1.printf("%s\n",**++cpp)

先搞清楚运算顺序,先对cpp进行++运算,再解引用两次。cpp原先指向甲,++运算后指向乙,第一次解引用后得到了C,再解引用并打印就可以得到POINT(悄悄地说一下,printf函数以%s的形式打印时,只要给出首元素的地址就能打印整个字符串了,平时用到的时候可能不会太注意,在这里就应该明白了).怎么样画图后分析思路清晰多了对吧?

2.printf("%s\n",*--*++cpp+3)

这题第一个难点就是运算的优先级,我会在文章末尾附上一张优先级表格,现在我们主要讲指针的运算。经过查表后我们得到了如下的顺序:先算++再解引用再--再解引用最后再+3.按照这个顺序,我们开始运算,先++,要注意的是在上一次打印中,cpp已经来到了乙的位置,所以++完之后,cpp指向了丙。解引用后我们得到了c+1这个地址,亦即B。再--,来到了A处,解引用,得到了E的地址(还记得之前说的c里面存放的是谁的地址吗?),最后+3,得到了POINT中第二个E的地址,接下来打印就可以得到ER。

3.printf("%s\n",*cpp[-2] + 3)

这一题我们要明白cpp[-2]其实就是*(cpp-2),编译器里实际上也是这么算的。明白了这个后我们就可以把上式改写成*(*(cpp-2))+3(最外面的那个括号是为了原式相对应)。由上一题我们知道cpp现在指向丙,-2后来到了来到了甲(注意,此时cpp的值并未改变,还是指向丙),两次解引用后得到了FIRST中F的地址,+3后指向了S的地址,打印就可以得到ST。

4.printf("%s\n", cpp[-1][-1] + 1)

参照上一题的解法,cpp[-1][-1]+1应当转化为*(*(cpp-1)-1)+1,cpp-1解引用后得到了地址c+2,地址c+2再-1就得到地址c+1,即B,解引用得到NEW的首元素N的地址,+1再打印即可得到EW.

 这道题不遗余力的向我展示了指针的强大与复杂,短短几行代码就牵扯出这么多内容,堪称是代码界的春秋笔法了。面对类似这种复杂的指针问题,我们可以画图来帮助我们分析,别在那里傻傻的空想,动起来。

附表

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值