指针运算笔试题解析:T1

题目:输出结果为?

#include 
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;
}

分析

数组c是一个字符指针数组,它里面存放的是四个指针,它们分别是这四个字符串首元素地址。数组cp里面存放的c是数组c首元素地址,首元素类型是char*,那它地址类型就是char**了。c指向的是ENTER,那么也可以推出c+1指向NEW(因为它的类型是char*,加1就会移动一个char*的大小,指针会移到NEW地址最前面),同理也可以得到c+2和c+3的对应关系了。
cpp是三级指针,是数组cp首元素c+3的地址

第一个输出

printf(“%s\n”, *++cpp)
首先cpp先++,那它原来指向c+3,现在就指向第二个元素c+2,然后进行一次解引用,那就变成
(c+2),c+2解引用就是POINT的地址咯,使用%s打印出来就得到POINT。

补充

Q:为啥POINT的指针打印出来就是POINT,不用再解引用一次吗?
A:printf 打印单个变量的时候传变量名即可,但打印字符串的时候,传的是字符串的地址。此外,printf在打印的时候要是遇到 \0,就会停止打印(类似strlen数字符串长度)

#include
int main()
{
	int a = 0;
	printf("%d\n", a);

	char b[] = { "bit" };
	printf("%s\n", b);

	char* arr[] = { "perfect","great"};
	printf("%s\n", arr[0]);    //arr[0] 是perfect第一个字符的地址

	return 0;
}

输出结果如图:
指针运算笔试题解析:T1_第1张图片
所以,要打印字符串就可以直接双引号加字符串,也可以%s 然后逗号后面加上字符串地址。

注意

在第一次输出中,cpp先++,此时cpp已经赋值加1,这个会影响到后续三次打印涉及的运算,即进行第一次输出后,cpp 指向第二个元素c+2,后续进行++运算带来的影响也会持续下去。

第二个输出

printf(“%s\n”, ++cpp+3)
cpp先++,现在指向c+1,解引用得到c+1,c+1指向NEW的地址,然后–使它指向ENTER的地址,再解引用得到该地址(就是数组c里面的字符指针,这个指针现在是E的地址),最后+3这一步,指针右移到E,打印得到ER

Q:为啥c+1 --之后指向ENTER的地址?
A:c+1的类型是char**,它–后会往前移动一个char的大小,而数组c的元素恰好就是char类型,所以–后刚好指向第一个元素。

Q:最后+3那一步咋理解?
A:此时+3的左边是数组c里面的指针,类型是char*,+3会移动3个字符类型的大小,移动3个字节就到第四个字符咯。(其实就简单的指针运算而已)

第三个输出

printf(“%s\n”, *cpp[-2]+3)
首先cpp[ -2 ] 可以写成 *(cpp-2)的形式,之前它指向c+1,减2后指向c+3,解引用一下就得到FIRST的地址,再加个3,指针指向S,打印出来就是ST

第四个输出

printf(“%s\n”, cpp[-1][-1]+1);
首先cpp[ -1 ] 写成 *(cpp - 1),后面那个也同理,即 (cpp-1)-1),注意此时cpp仍指向c+1,上面那个 -2不是赋值,不影响cpp的指向。-1后指向c+2,解引用一下得到c+2,给它减个1就指向NEW的地址,加个1照葫芦画瓢,输出就是EW。ok四道题搞完了!

指针运算笔试题解析:T1_第2张图片

总结

只要能理清楚三级指针的指向关系,以及注意++和–带来的改变,这道题就基本没啥难度了。

你可能感兴趣的:(c语言,开发语言)