经典奇葩面试题:C++中字符串的数组指针与指针数组

今天看到一个巨变态和奇葩的C++题目,花了很久才弄懂为什么。手头书上的答案还有误,因此特意记录下来。

题目如下:

判断输出:

#include<stdio.h>
int main()
{

	char *str[]={"Welcome","to","Fortemedia","Nanjing"};
	char **p=str+1;
	str[0]=(*p++)+2;
	str[1]=*(p+1);	
	str[2]=p[1]+3;
	str[3]=p[0]+(str[2]-str[1]);

	printf("str[0]=%s\n",str[0]);
	printf("str[1]=%s\n",str[1]); 
	printf("str[2]=%s\n",str[2]); 
	printf("str[3]=%s\n",str[3]); 

	return 0;
}

在逐步分析之前先举个例子:

对于常规的指针来说,比如:

int b=1;
int* a=&b;

那么输出*a,是1;输出a,是b的地址。

但是,char*是个特殊的指针例子。比如:

char *str="this is a test";

这时候,输出*str,只会输出“t”;

输出str,显示的并不是地址,而是“this is a test”(完整的字符串)!

如果先执行str=str+2,那么输出str,会输出“is is a test”;输出*str,会输出“i”。


现在开始一句一句看上面的题目:

char *str[]={"Welcome","to","Fortemedia","Nanjing"};
char **p=str+1;

第一句*str[ ],定义的是一个指针数组,数组的名字叫str,每个元素是一个字符串指针;

第二句,**p=str+1,那么这个p,是一个指针,指向了另一个指向字符串的指针。

(这里隐含了一个重要的信息!即:p=&str[1];)

那么这时,*p指向的是“to”的首地址:

如果输出*p,输出的是“to”;

如果输出**p,输出的是“t”;

如果输出p[0],会输出“to”(p[0]就相当于*p了!这就好比数组a[10],输出*a其实就是a[0],一码事)

如果输出p[1],会输出“Fortemedia”

如果输出p[2],会输出“Nanjing”

然后:

str[0]=(*p++)+2;

这句话有个陷阱:

*p++究竟是“ (*p)++ ”  还是“  *(p++) ”?

查阅资料可知,++的优先级高于*,因此是p++(p自增),而不是(*p)++(不是*p自增)

因为是后置加法,返回的是未自增以前的p!

 

str[0]=(*p++)+2等同于:

1. str[0]=*p+2;(这里的p是自增以前的p,str[0]在加2前,指向“to”首地址,加完2,指向的是to中的第三位,即结尾符“\0”)

2. p=p+1;(同样隐含了一个重要信息:p=&str[2],这个之后会用到!!留意!;p此时指向了一个指向字符串"Fortemedia"的指针str[2])。

那么输出str[0],显示为空,其实是输出的“\0”。


ps:关于上面这个,我要说一点:有的辅导书上写的是错的,他们说,先p自增,跑到了Fortemedia这里,即str[2],然后又加了个2,跑到了str[4],而str[ ]数组只有1到3,str[4]是空,所以str[1]被赋值为空。

这纯粹是胡说八道。说明写书的人自己都不懂。如果不信,可以把上面的str换一下:

char *str[]={"Welcome","toa","Fortemedia","Nanjing"};(即把第二个to改成toa)

那么执行str[0]=(*p++)+2;输出str[0],不是空,而是a。

符号优先级代表的是结合的优先级,而不是执行顺序。str[0]=(*p++)+2并不代表我要先把p++再取*再加2;而是意味着是p自增,而不是*p自增。实际上是先*再+2,最后p自增)


之后:

str[1]=*(p+1);

我们知道p已经指向了str[2]的地址,也就是指向了一个指向字符串"Fortemedia"的指针。p+1,是str[2]的地址加1,那么返回str[3]的地址,取*,得到指向“Nanjing”的指针,因此输出str[1],是“Nanjing”。

再之后:

str[2]=p[1]+3;

p此时指向一个指向Fortemedia的指针,p[0]则相当于是*p,是指向Fortemedia的指针。p[1]指向了最后的Nanjing字符串首地址。

p[1]+3,得到指向“jing”的首地址的指针,返回str[2]中

注意到前面的重要信息,p=&str[2],str[2]改变了,p也随之改变,因此p指向了一个指向“jing”的指针。

事实上这句话与*p=p [1]+3等价。

输出str[2],结果为“jing”。


最后:

str[3]=p[0]+(str[2]-str[1]);

我们要知道,p[0]相当于是*p,是指向“jing”的指针;

str[2]也是指向“jing”,str[1]我们刚刚知道,指向“Nanjing”。

(str[2]-str[1])得到3。

p[0]指向jing的指针,再加3,指向了g,因此str[3]输出g。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值