首页 > 试题广场 >

下列代码的输出是什么?()

[单选题]
下列代码的输出是()
#include<stdio.h>

int main() {
    const char *c[] = {"HELLO", "NEW", "WORLD", "SAYHI"};
    const char **cp[] = {c + 3, c + 2, c + 1, c};
    const char ***cpp = cp;
    printf("%s,", **++cpp);
    printf("%s,", *--*++cpp + 3);
    printf("%s,", *cpp[-2] + 3);
    printf("%s\n", cpp[-1][-1] + 1);
    return 0;
}


  • WORLD,LO,SAYHI,EW
  • WORLD,LO,HI,NEW
  • NEW,LO,SAYHI,EW
  • WORLD,LO,HI,EW
答案:D;
第一个printf:由于char***cpp,可以读成cpp为一个指向char**类型的指针,并且初始化为cp,而cp是一个指针数组,数组里面存储的类型为char**,也就是cpp指向cp[0],故*cpp=cp[0];因此++cpp使得cpp指向cp[1],故*++cpp=cp[1];而cp[1]是一个指向c[2]的指针,因此*cp[1] = c[2],故**++cpp=*cp[1]=c[2],故输出WORLD;
第二个printf:由优先级可得知,单目运算符高于算术运算符;而*和++是单目运算符,+是算术运算符,又cpp本身是指向的cp[1],故++cpp使得cpp指向cp[2],故*++cpp则为cp[2],而此时的cp[2]是一个指向c[1]的地址,故对指向c[1]的指针cp[2]进行--,故使得cp[2]指向的是c[0],故*--*++cpp+3=*--cp[2]+3=c[0]+3,而这里的c[0],其实存放的是指向HELLO字符串的指针故c[0]+3,使得该指针指向HELLO中的第二个L的位置,故输入LO;
第三个printf:由于cpp目前指向的是cp[2],而cpp[-2]是等于*(cpp-2),而在第二个printf时cpp指向cp[2],则*(cpp-2) = cp[0](注:这里cpp-2后,cpp本身的指针地址没有改变,因此在第四个printf中,cpp依旧是指向cp[2]),又cp[0]是一个指向c[3]的指针,对cp[0]进行*运算,使得*cp[0]=c[3],故**(cpp-2)=*cpp[-2]=c[3],同时c[3]是一个指向SAYHI的指针,故c[3]+3,使得指向H的位置,故输出HI;
第四个printf:在第三个printf并没有改变cpp的地址,故cpp依旧是指向cp[2],又cpp[-1][-1]+1=*(*(cpp-1)-1)+1,故cpp-1,则cpp指向cp[2],故*(cpp-1)=cp[1];此时的cp[1]是一个指针,指向c[2],故cp[1]-1是从指向c[2]的指针地址-1,故是指向c[1],则*(*(cpp-1)-1)=*(cp[1]-1)=c[1],故cpp[-1][-1]+1=*(*(cpp-1)-1)+1=c[1]+1,此时的c[1]同样是一个指针,故c[1]+1是指向NEW中的E的位置,故输出EW。
故答案是D。
编辑于 2017-08-11 23:09:50 回复(10)
哪位大佬可以解释下?
发表于 2017-08-11 17:25:50 回复(0)
实际代码中这么写会被砍(⊙﹏⊙)
发表于 2017-09-06 16:54:05 回复(5)
发表于 2017-08-21 00:29:05 回复(4)

解答: 
c是一个指针数组,每个数组元素都是char*类型的指针,值分别是那些字符串(的首地址):

c[0] = "HELLO" 
c[1] = "NEW" 
c[2] = "WORLD" 
c[3] = "SAYHI"

而[]和*是本质一样的运算,即c[i]=*(c+i)。

c和c+i都是char *[]类型,它可以退化成char **类型,再看cp,它正好是一个char **的数组,来看它的值:

cp[0] = c + 3 
cp[1] = c + 2 
cp[2] = c + 1 
cp[3] = c

引用后就有:cp[0][0]=*(c + 3)=c[3]="SAYHI",以此类推。

cp是char **[]类型,它可以退化成char ***类型,看最后的cpp,它正是char ***类型,它是一个指针变量,和上面两个不同,上面两个是数组。

这样分析过后,下面的解析就一目了然了:

  • printf("%s",**++cpp); 
    ++cpp的值是cp+1,引用一次后是cp[1]再引用是*cp[1]=c[2]="WORLD",第一句的输出
  • printf("%s",*--*++cpp+3); 
    再++cpp的值是cp+2,引用一次是cp[2]=c+1,再对这进行--,减后是c再引用是c[0]="HELLO"再+3,字符串指针指到"LO",输出是"LO"
  • printf("%s",*cpp[-2]+3); 
    这时cpp的值是cp+2,cpp[-2]=*(cpp-2)=*(cp+2-2)=cp[0]=c+3,再引用是c[3]="SAYHI",+3 字符串指针指到"HI",输出是"HI"
  • printf("%s\n",cpp[-1][-1]+1); 
    cpp还是cp+2,cpp[-1]=*(cpp-1)=*(cp+2-1)=cp[1]=c+2,再[-1]得*(c+2-1)=c[1]="NEW",+1字符串指针指到"EW",输出是"EW"。
发表于 2018-04-03 14:41:53 回复(0)
本题比较坑的地方,千万记着++或者--改变cpp的值了。
比较容易理解的方法**++cpp,比较简单 *++cpp=c+2,所以为world
*--*++cpp+3=*--(c+1)+3=*c+3=LO
此时cpp已经累加了2次。
*cpp[-2]+3=**(cpp-2)+3=**cp+3=*(c+3)+3=HI
cpp[-1][-1]+1=*(*(cpp-1)-1)+1=*(c+2-1)+1=EW
然后答案就出来了,看最高赞的答案头晕,有200字小短文的长度了吧。这种直接根据数学做不是快捷不晕嘛

发表于 2018-05-01 18:54:36 回复(1)

发表于 2019-04-24 16:31:18 回复(0)
这样搞真的可以活到明天吗
编辑于 2018-09-09 08:55:37 回复(1)
用arr[x] = *(arr+x)这个公式代换就行了,关注运算符的优先级
发表于 2017-08-17 21:36:03 回复(0)
每一步都会改变cpp的值,所以cpp并非保持初始化时的值不变。
发表于 2019-07-08 08:31:11 回复(0)
这道题是典型为了考试而考试的题。项目这样写,坟头草都比人高了
发表于 2022-01-09 22:27:56 回复(0)
*cpp[-2]=cp[0],指针地址依旧不变,故选D。
发表于 2018-11-24 16:14:43 回复(1)
看吐了
发表于 2023-11-20 17:05:50 回复(0)
发表于 2023-08-08 21:19:18 回复(0)
注意每步操作后的三级指针cpp的指向变化。
发表于 2022-10-12 22:13:06 回复(0)
这么写代码不得直接被毕业了?
发表于 2022-09-16 14:35:46 回复(0)
禁止套娃
发表于 2022-05-29 20:18:46 回复(0)
答案:D;
第一个printf:由于char***cpp,可以读成cpp为一个指向char**类型的指针,并且初始化为cp,而cp是一个指针数组,数组里面存储的类型为char**,也就是cpp指向cp[0],故*cpp=cp[0];因此++cpp使得cpp指向cp[1],故*++cpp=cp[1];而cp[1]是一个指向c[2]的指针,因此*cp[1] = c[2],故**++cpp=*cp[1]=c[2],故输出WORLD;
第二个printf:由优先级可得知,单目运算符高于算术运算符;而*和++是单目运算符,+是算术运算符,又cpp本身是指向的cp[1],故++cpp使得cpp指向cp[2],故*++cpp则为cp[2],而此时的cp[2]是一个指向c[1]的地址,故对指向c[1]的指针cp[2]进行--,故使得cp[2]指向的是c[0],故*--*++cpp+3=*--cp[2]+3=c[0]+3,而这里的c[0],其实存放的是指向HELLO字符串的指针故c[0]+3,使得该指针指向HELLO中的第二个L的位置,故输入LO;
第三个printf:由于cpp目前指向的是cp[2],而cpp[-2]是等于*(cpp-2),而在第二个printf时cpp指向cp[2],则*(cpp-2) = cp[0](注:这里cpp-2后,cpp本身的指针地址没有改变,因此在第四个printf中,cpp依旧是指向cp[2]),又cp[0]是一个指向c[3]的指针,对cp[0]进行*运算,使得*cp[0]=c[3],故**(cpp-2)=*cpp[-2]=c[3],同时c[3]是一个指向SAYHI的指针,故c[3]+3,使得指向H的位置,故输出HI;
第四个printf:在第三个printf并没有改变cpp的地址,故cpp依旧是指向cp[2],又cpp[-1][-1]+1=*(*(cpp-1)-1)+1,故cpp-1,则cpp指向cp[2],故*(cpp-1)=cp[1];此时的cp[1]是一个指针,指向c[2],故cp[1]-1是从指向c[2]的指针地址-1,故是指向c[1],则*(*(cpp-1)-1)=*(cp[1]-1)=c[1],故cpp[-1][-1]+1=*(*(cpp-1)-1)+1=c[1]+1,此时的c[1]同样是一个指针,故c[1]+1是指向NEW中的E的位置,故输出EW。
故答案是D。
发表于 2022-05-15 15:34:36 回复(0)
首先弄清楚c、cp、cpp都是什么内容
char *c[] = {"HELLO", "NEW", "WORLD", "SAYHI"};这说明了c是一个char*类型的数组,其中每页元素都是一个指向字符数组的指针,我们都知道指向数组的指针都是默认在第一个元素处,c[0]指向"HELLO"的“H”,c[1]指向"NEW"的“N”,c[2]指向"WORLD"的“W”,c[3]指向"SAYHI"的“S”。
char **cp[] = {c + 3, c + 2, c + 1, c};cp是一个char**类型的数组,内部的每一个元素都是指针,并且指向的是字符型指针数组的指针,并且复制后,cp[0]指向c+3,即指向c[3],同理cp[1]指向c[2],cp[2]指向c[1],cp[3]指向c[0].
char ***cpp = cp;cpp是一个指针,指向char**类型变量的指针,即cpp是一个指向字符型指针数组的指针数组的指针赋初值cp,cpp指向cp数组,所以*cpp=cp[0]。
printf("%s,", **++cpp);++cpp指针加一,所以指向cp[1],*++cpp=cp[1],**++cpp=*cp[1]=c[2]="WORLD"。
printf("%s,", *--*++cpp + 3);c++运算逻辑关系中也规定单目运算符比双目运算符优先级高,所以先算单目运算符,由上一条语句可知cpp此时已经指向cp[1]了,
所以++cpp后,cpp指向cp[2],*++cpp=cp[2],--*++cpp=--cp[2],cp[2]此时指向c[0],*--*++cpp=*c[0],c[0]此时是指向"HELLO"的“H”,+3,向后移动3个位置从“L”开始,所以输出为“LO”。
printf("%s,", *cpp[-2] + 3);cpp此时指向cp[2], *cpp[-2]取得cp[0]的内容而cpp指针位置并未移动(运算后并未赋值回给cpp),cp[0]此时指向c[3],c[3]此时指向"SAYHI"的“S”,+3后向后移动3个位置,从“H”开始,所以输出的是“HI”。
printf("%s\n", cpp[-1][-1] + 1);cpp此时仍然指向cp[2],cpp[-1]指向cp[1],cp[1]此时指向c[2],cpp[-1][-1]相当于指向c[1],c[1]指向"NEW"的“N”,+1向后移动1位,从“E”开始取,所以输出的是“EW”。


发表于 2022-03-30 10:14:51 回复(0)
// *++cpp=*(cp+1)=cp[1] cp[1]=c+2 即*cp[1]=*(c+2)= c[2] = world (输出格式为s) printf("%s\n", **++cpp);  // *++cpp = cp[2] = c+1 *--cp[2] = *(cp[2]-1) = *(c+1-1)=*(c)=hello // *c + 3 即c[0][3]=lo(输出格式为s) printf("%s\n", *--*++cpp + 3);  // cpp此时指向的是cp[2] cpp[-2]=*(cpp-2)=cp[0]=c+3 *cpp[-2]=*(c+3)=c[3]=sayhi // c[3]+3 = c[3][3]=hi(输出格式为s) printf("%s\n", *cpp[-2] + 3);  // cpp此时指向的是cp[2] 将cpp看成三维指针数组 //  2-1=1 即cpp[-1]=cp[1]=c+2指向的是world cpp[-1][-1]=new // cpp[-1][-1] + 1 = cpp[-1][-1][1] = ew(输出格式为s) printf("%s\n", cpp[-1][-1] + 1);
 // *++cpp=*(cp+1)=cp[1] cp[1]=c+2 即*cp[1]=*(c+2)= c[2] = world (输出格式为s)
    printf("%s\n",  **++cpp);

    // *++cpp = cp[2] = c+1 *--cp[2] = *(cp[2]-1) = *(c+1-1)=*(c)=hello
    // *c + 3 即c[0][3]=lo(输出格式为s)
    printf("%s\n",  *--*++cpp + 3);

    // cpp此时指向的是cp[2] cpp[-2]=*(cpp-2)=cp[0]=c+3 *cpp[-2]=*(c+3)=c[3]=sayhi
    // c[3]+3 = c[3][3]=hi(输出格式为s)
    printf("%s\n",  *cpp[-2] + 3);

    // cpp此时指向的是cp[2] 将cpp看成三维指针数组
    //  2-1=1 即cpp[-1]=cp[1]=c+2指向的是world cpp[-1][-1]=new
    // cpp[-1][-1] + 1 = cpp[-1][-1][1] = ew(输出格式为s)
    printf("%s\n",  cpp[-1][-1] + 1);


发表于 2022-03-09 14:51:03 回复(0)