首页 > 试题广场 >

下面程序应该输出多少?

[单选题]
下面程序应该输出多少?
char *c[] = { "ENTER", "NEW", "POINT", "FIRST" }; 
char **cp[] = { c+3, c+2, c+1, c }; 
char ***cpp = cp; 

int main(void)
{ 
    printf("%s", **++cpp); 
    printf("%s", *--*++cpp+3); 
    printf("%s", *cpp[-2]+3); 
    printf("%s\n", cpp[-1][-1]+1); 
    return 0;
}

  • POINTERSTEW
  • FERSTEPOINW
  • NEWPOINTW
  • POINTFIREST
推荐
虽然项目中不这么用,但是要答对还是需要扎实的基础知识。
其中考了指针应用,隐含中也考了运算符优先级的问题(*--*++cpp+3)
具体运算符优先关系记忆这个写的比较好http://blog.csdn.net/skywalker_leo/article/details/6237222
c是一个指针数组,每个数组单元都是一个指针,指向一个字符创。
即c[0]="ENTER"......c[3]="FIRST"
由于[]与*运算本质几乎是一致的,以下用[]替换*更容易理解。
c[i]=*(c+i)
c和c+i都是char*[]类型,它可以退化成char**类型,它正好是一个char**数组
cp[0]=c+3 .....cp[3]=c
引用后cp[0][0]=*(c+3)=c[3]="FIRST"
cp是char**[]类型,它可以退化成char***类型,正好与cpp类型一致。
1>++ccp的值是cp+1  *++p=*(cp+1)=cp[1]  **++p=*(cp[1])=c[2]="POINT"
2>运算符优先级决定运算先后关系
++ccp的值是cp+2 *++p=*(cp+2)=cp[2]=c+1 --*++p=c *--*++p=*(c+0)=c[0]="ENTER"再+3字符串指向"ER"
3>cpp的值为cp+2 cpp[-2]=*(cpp-2)=*(cp+2-2)=cp[0]=c+3再引用*(c+3)=c[3]="FIRST"字符串指到"ST"
4>cpp的值没变,cpp[-1]=*(cpp-1)=*(cp+2-1)=cp[1]=c+2再[-1]得*(c+2-1)=c[1]="NEW",+1字符创指针指到"EW"
翻来覆去,记得这个换算关系式即可,c[i]=*(c+i)。
编辑于 2016-10-21 10:58:24 回复(7)
参看http://blog.csdn.net/yuanjilai/article/details/8043784讲解的非常详细
发表于 2015-08-14 14:39:06 回复(0)
前面的解析已经不错了,不过结合图片可能会更清晰点吧:
首先看 C,CP,CPP 之间的存储关系


计算各个表达式结果的过程如下图

更多关于指针的内容可以参考我的 Github:
https://github.com/xuelangZF/CS_Offer/blob/master/C%2B%2B/Pointer.md

编辑于 2016-09-14 11:20:09 回复(27)
项目里面谁要写这种, 等着被开除的节奏
发表于 2015-03-19 10:02:14 回复(21)

做这道题之前,我们先明确几个概念:

1、p++,p--,++p,--p会影响指针的指向。

例如: 

  ++p相当于p = p + 1;     指针会保存改变后的指向。

2、p+2;这样表达式运算完后,指针指向不会受到影响,因为它并未保存改变后的指向。

3、数组与指针之间的转换:

例如:

  p[2] = *(p+2);p为数组首地址,p相当于&p[0],p+2相当于&(p+2),最左边加*,表示取值,即p[2]。

  p[-1][-1] = *(*(p-1)-1);同理

分析:
① 对于 **++cpp来说,一开始cpp指向cp,即指向存放c+3的地址,

然后表达式先执行++cpp,指针后移,且保存指向,即指向存放c+2的地址,

之后*++cpp,解一层引用,指向地址中的内容c+2,即指向*c[]中存放第三个字符串的地址,

再执行**++cpp,即指向这个字符串的第一个的元素P,

然后输出,从P开始输出,遇到'\0'结束,即输出 POINT

 

② 对于*--*++cpp+3来说,现在cpp已经指向存放c+2的地址了,

先执行++cpp,即cpp指向存放c+1的地址,

然后执行*++cpp,即cpp指向*c[]中存放第二个字符串的地址,

再执行--*++cpp,即cpp指向*c[]中存放第一个字符串的地址,

再执行*--*++cpp,即cpp指向第一个字符串的第一个字符E,

再执行*--*++cpp+3,即cpp指向第一个字符串的第四个字符E,

再输出,结果为ER

 

③ 对于*cpp[-2]+3,目前cpp指向存放c+1的地址,

将表达式化简一下,即**(cpp-2)+3,

先执行cpp-2,cpp指向存放c+3的地址,

然后执行*(cpp-2),cpp指向*c[]中存放第四个字符串的地址,

再执行**(cpp-2),cpp指向第四个字符串的第一个字符F,

再执行**(cpp-2)+3,cpp指向第四个字符串的第四个字符S,

再输出,结果为ST

 

④ 对于cpp[-1][-1]+1,现在cpp还是指向存放c+1的地址,

将表达式化简一下,即*(*(cpp-1)-1)+1,

先执行cpp-1,cpp执行存放c+2的地址,

然后执行*(cpp-1),cpp指向*c[]中存放第三个字符串的地址,

再执行*(cpp-1)-1,cpp指向*c[]中存放第二个字符串的地址,

再执行*(*(cpp-1)-1),cpp指向第二个字符串的第一个字符N,

再执行*(*(cpp-1)-1)+1,cpp指向第二个字符串的第二个字符E,

再输出,结果为EW

最后结果为A,POINTERSTEW

发表于 2019-07-15 18:05:28 回复(3)
首先*c[]等价于c[][]
**cp[]等价于*cp[][]
***cpp等价于*cpp[][]
所以cpp和cp其实指向的是相同的地方。
然后*和++是属于同一个优先级的,它的结合方式是右结合比如*++cpp等价于*(++cpp)
1、**++cpp:**(++cpp) ++cpp指向了c+2为point  **(++cpp)就为POINT;
2、*--*++cpp+3等价于*(--*(++cpp))+3所以*(++cpp)就指向了c+1,--(c+1)就指向了c所以输出的为ER;
3、cpp[-2]相当于cpp-2指向了c+3,*(c+3)+3输出就为ST
4、在步骤3中cpp并没有发生改变,cpp[-1]相当于*(cp+1)为(c+2)然后 (c+2)[-1]相当于c[1] 最后+1为EW;
编辑于 2015-10-21 10:10:04 回复(0)
**++cpp :首先cpp 移动到cp+1的地方 然后取 两次* 相当于 **(cp+1) 结果就是POINT 移动cpp到cp+1的位置

*--*++cpp+3 :首先cpp移动到cp+2的地方 然后取* 相当于 *--cp[2]+3 然后 --cp[2]的话相当于 --(c+1) 就等于c  就变成了 *c+3  输出ER    移动cpp到cp+2   cp[2]变成c

*cpp[-2]+3: 首先 cpp[-2] = *(cpp-2) [cpp=cp+2]   =  **cp+3 结果 ST 没有移动

cpp[-1][-1]+1: 首先cpp[-1]   -> *(cp+1) -> c+2  然后 (c+2)[-1] -> (c+2)[-1] -> *(c+2-1) -> c[1]      然后 c[1]+1    就变成了 EW

结果就是A

这个题目中 中间 cpp 变动两次,cp[2] 变动一次 特别注意  cp[2] 是数组 里面内容可以变动
编辑于 2015-10-20 11:42:00 回复(1)

char *c[] = { "ENTER", "NEW", "POINT", "FIRST" };

char **cp[] = { c+3, c+2, c+1, c };

char ***cpp = cp;

int main()

{

    printf("%s", *(*(++cpp)));

    printf("%s", (*(--(*(++cpp))))+3);

    printf("%s", (*(*(cpp-2)))+3);

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

    return 0;

}

更好理解,排除运算符号的影响。 结果运行如下: POINTERSTEW

发表于 2016-10-24 11:18:03 回复(0)
char *c[]是数组指针,四个指针分别指向题目里面给的四个单词数组。char **cp[]是指针的指针,也是四个指针分别指向前面的四个指针,不过顺序是反的。char ***cpp就是前面char **cp[]的指针,可以想象成一个指向数组的指针。
然后 printf("%s", **++cpp); 表示取char **cp[]里面的第二个指针指向的值,即c+2对应的值而c+2对应的是c[2]也就是"POINT"。下面的实在是太变态了,不想了也想不明白。。。。等高手来回答吧。
发表于 2015-04-02 15:55:22 回复(0)
这个主要是执行顺序的问题,我加了一下括号:
 printf("%s\n", **(++cpp)); 
 
 printf("%s\n", (*(--(*(++cpp)))) + 3);

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

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

发表于 2015-03-30 13:16:33 回复(0)
看的头痛。
发表于 2015-01-08 15:28:15 回复(1)
部分运算符的优先级如下:++ > -- > * > &,经运算可知选A。
编辑于 2018-11-27 20:41:11 回复(1)
这种纯粹有病,没有一点可读性,完全是炫耀型的指针用法!
发表于 2015-04-22 14:05:21 回复(1)
char*c[] = { "ENTER", "NEW", "POINT", "FIRST"};
char**cp[] = { c+3, c+2, c+1, c };
char***cpp = cp;
//指向c+2则为"POINT"
printf("%s", **++cpp);
//++cpp指向c+1,*++cpp指向"NEW",--*++CPP指向"ENTER",所以*--*++cppp为"ENTER",故*--*++cpp+3 向后移动3个字符所以结果为"ER"
printf("%s", *--*++cpp+3);
//*cpp[-2]向后移动2个位置为c+3,*cpp[-2]为"FIRST",所以*cpp[-2]+3 "ST"
printf("%s", *cpp[-2]+3);
//cpp[-1]在cpp[]的基础上向左移动一个位置为c+2为"POINT ",而cpp[-1][-1]则在c[]上向左移动一个位置则为" NEW ",所以 cpp[-1][-1]+1为:"EW"
printf("%s\n", cpp[-1][-1]+1);
发表于 2016-06-15 17:08:17 回复(3)
这种代码…哎😑
发表于 2024-05-17 10:25:46 回复(0)
c++太变态了
编辑于 2024-03-05 23:10:29 回复(0)
太摋比了这题目,把图画好然后记住:数组下标等价于*(数组名+下标)然后慢慢推就行,开发中不会有人这样写代码的
发表于 2023-12-19 23:50:23 回复(0)
对不起,看到这种题真的没有答得欲望。
发表于 2022-11-27 17:23:55 回复(0)
发表于 2022-10-03 21:26:56 回复(0)
什么题目????
发表于 2022-03-20 19:11:51 回复(0)
E0144    "const char *"类型的值不能用于初始化"char *" 类型的实体

发表于 2020-09-14 16:53:58 回复(0)