笔试题1:
第一个是首元素的地址再加一,指向第二个元素,再解引用,最后打印的就是2;
第二个,&a+1,取出整个地址再加一,指向5的后面,是一个数组指针,然后强转成整型指针;再减一,最后打印的就是5
笔试题2:
p是结构体指针,p+0x1就是p+1,跳过一个结构体的大小,这里结构体的大小是20,所以打印的结果就是00100014(20换算成16进制就是14,位数不够在前面补0,因为测试是在x86的环境下,所以指针是8位16进制);
第二个把p强转成unsigned long型,也就是整数类型,加一就是加一,打印00100001;
第三个把p强转成unsigned int*类型,加一跳过一个整型的大小,打印00100004;
如果把%p换成%x,打印的就是16进制的数字,而不是地址,前面的0就没有意义了:
第三题:
&a是数组指针,+1跳过整个数组,再强转为整型指针,ptr1[-1]其实就等于*(ptr1-1),也就是4,打印也就是4;
对于第二个打印,a表示首元素地址,在这里是0x006ffe48,(下图)强转成整型,即7339592,再加一,得到7339593,再强转为整型指针,就是0x006ffe49;所以ptr2就是0x006ffe49;也就是指针加一,跳过一个字节,这时请看下面我画的图:
ptr2即指向“01”的后面,然后解引用,因为是int型指针,所以向后解引用4个字节,到“02”的后面,因为是小端存,所以再以小端的形式拿出来,即0x 02 00 00 00(16进制),因为是以16进制打印,所以就是2000000。
对于我自己而言,这题还是很重量级的,由于对于地址加一的理解不够,我自己是想了好久好久。
第四题:
这题,我们可以注意到(0,1),(2,3),(4,5);这其实是逗号表达式,最后一个表达式的结果就是它的结果,所以其实是 int a[3][2] = { 1 , 3 , 5 } ;剩下三个就是0,a[0]是数组名,即第一行第一个元素的地址,所以p就指向1,p[0]可以写成*(p+0),就是1;
第五题:
第五题也是重量级的,像这种题目就要好好画图了,让我们仔细研究一下:
a[4][2]已经在图中标注出来了;接着将 a 赋给 p ,a表示首行的地址,是数组指针,类型是int(*)[5],放入 p 中(p的类型是int (*)[4]),因为类型不同,编译器会说一下,但是也只是说一下而已,是可以放进去的,接着,p[4][2]可以写成*(*(p+4)+2);p+4跳过16个字节的大小(注意p的数组元素个数是4,不是5,不要跳过20个字节了),再解引用,得到图中蓝色的部分,这时p+4作为数组名,表示首元素的地址,再+2,跳过两个字节,再解引用,得到图中的绿色的元素;
看到打印的结果是两个指针的相减,显然后面一个是-4;而-4的原反补码是:
10000000 00000000 00000000 00000100
11111111 11111111 11111111 11111011
11111111 11111111 11111111 11111100
换算成16进制,即0x ff ff ff fc;对于地址而言,其实没有原反补码的概念,打印出来的就是0x ff ff ff fc;
第六题:
&aa得到整个二维数组的地址,再+1,跳过整个二位数组,指向10的后面,再强转为整型指针,ptr1就指向10的后面,再减一,就指向了10,解引用得到10,打印的就是10;
aa表示第一行的地址,再加一,表示第二行的地址,再解引用,得到的其实是第二行的数组名,如果不能理解的话,还可以把*(aa+1)改写成aa[1],即第二行的数组名,即第二行首元素的地址,这时的强转其实已经多余了,再减一,得到的就是5;
第七题:
a是一个指针数组,每一个元素是一个指针,指向字符串的首个字符;数组名a表示首元素的地址,也就是第一个指针的地址,将其地址放入pa中,类型是二级指针,接着pa++;跳过一个字符指针的大小,指向第二个指针,再解引用pa,得到的是第二个指针,也就是 'at' 的首元素 'a' 的地址,我们知道,printf函数的参数是指针,所以打印首字符的地址也就是打印整个字符串,也就是 "at" ;
-->
第八题:
像这样复杂的题目,画图是最好的方法:
画好图之后,我们看第一个:printf("%s\n", **++cpp);
首先执行++cpp,也就是cpp自增,指向了c+2,再解引用,得到了c+2里面的内容,即指向了 c 中的第三个指针元素,再解引用,得到了char*的内容,即指向了"POINT"的首元素'p',所以打印的应该就是POINT(等全部分析完再看结果):
接着,我们看第二个:printf("%s\n", *--*++cpp+3);
首先执行的是++cpp,因为上面cpp已经指向了c+2,所以这是的cpp指向了c+1,解引用的优先级是高于加号的,所以我们接下来解引用,得到c+1的内容,即指向了 c 中的第二个指针元素,再--,即指针指向了 c 中的第一个元素指针,再解引用,得到第一个char*的内容,即指向了"ENTER"的首元素'E',接着再+3,指向了'E',所以打印的结果应该是"ER":
继续,我们看到第三个:printf("%s\n", *cpp[-2]+3);
cpp[-2]可以写成 *(cpp-2),所以结果就指向了c+3(但是cpp还是指向的c+1),再解引用得到c+3的内容,即指向了 c 的第四个元素,再解引用,得到第四个元素的内容,即指向了"FIRST"的'F',再+3,即指向了'S',所以打印的结果应该是"ST":
终于到最后一个了:printf("%s\n", cpp[-1][-1]+1);
cpp[-1][-1]可以写成 ((app-1)-1),cpp减一,指向了c+2,再解引用,得到c+2的内容,再减一,指向了c 的第二个元素,再解引用,得到它的内容,即指向了"NEW"的首字符'N',再加一,指向了'E',所以最后打印的结果应该是"EW":
接下来,见证奇迹的时刻到了!
只能说:完美!
好了,以上就是指针8道笔试题的所有内容了,希望对你有所帮助喽。