目录
一. 前言
本小节将会给小伙伴们分享一些关于6道指针的笔试题,希望能给大家带来一些收获。
二. 正文(以下代码在x86_32位,小端下运行)
1.
int main (){int a [ 5 ] = { 1 , 2 , 3 , 4 , 5 };int * ptr = ( int * )( & a + 1 );printf ( "%d,%d" , * ( a + 1 ), * ( ptr - 1 ));return 0 ;}// 程序的结果是什么?结果: 2 5
解析:
第一空:首先&a意思是表示取得整个数组地址,+1后呢,则是跳过整个数组,再强转为整型指针,*(a + 1) 也容易知道是第二个元素;*(ptr - 1)就很容易理解了,prt是int指针,退后一个int单位,结果就是5。
2.
// 结构体的大小是 20 个字节struct Test{int Num ;char * pcName ;short sDate ;char cha [ 2 ];short sBa [ 4 ];} * p ;// 假设 p 的值为 0x100000 。 如下表表达式的值分别为多少?int main (){p = 0x100000;printf ( "%p\n" , p + 0x1 );printf ( "%p\n" , ( unsigned long ) p + 0x1 );printf ( "%p\n" , ( unsigned int* ) p + 0x1 );return 0 ;}// 结果是:00100014 00100001 0010 0004
解析:
第一空:p我们知道是一个结构体指针变量,然后放着0x100000,补全0为0010 0000。p + 0x1,我们知道给指针+1要看指针指向的类型,可知是个20字节的结构体所以在16进制上增加20字节,
即加上14,而最后是在32为机器,以地址形式打印那么为00100014。
第二空:前面分析同一空类似,题中将p强制转化为整型,不再是地址,那么就是加1,然后我们一地址型式打印,即为00100001。
第三空:同理, 将本是结构体地址转化为整型地址,那么+1就是加个整型--4个字节,即00100004。
3.
int main (){int a [ 4 ] = { 1 , 2 , 3 , 4 };int * ptr1 = ( int * )( & a + 1 );int * ptr2 = ( int * )(( int ) a + 1 );printf ( "%x,%x" , ptr1 [ - 1 ], * ptr2 );return 0 ;}// 结果:4 200 0000
解析:
第一空: 这个就很简单了,基本的访问了,%x以16进制输出有效数字。
第二空: 就有些复杂了,首先我们先将a在内存中的存储,以16进制形式写出来,机器是32位,和小端存储,
然后将a地址转成整型加 1 ,然后再转回int类型地址就是只移动一个字节。
最后解引用整型,访问4个字节的内容,以小端特性取出,并以16进制打印出来。
也就是答案: 200 0000
4.
int main (){int a [ 5 ][ 5 ];int ( * p )[ 4 ];p = a ;printf ( "%p,%d\n" , & p [ 4 ][ 2 ] - & a [ 4 ][ 2 ], & p [ 4 ][ 2 ] - & a [ 4 ][ 2 ]);return 0 ;}// 结果是 FFFFFFFC -4
解析:
数组如图:
所以&p[4][2] - &a[4][2] = -4, 但这是人为的计算,计算机可不认识,所以还得换成补码
-4 补码: 1111 1111 1111 1111 1111 1111 1111 1100
然后,以%d 形式打印就是 -4; 以%p形式打印,这里可以可以理解为 把补码当成地址来打印,转化为16进制是 FFFFFFFC
5.
#include <stdio.h>int main (){char * a [] = { "work" , "at" , "alibaba" };char** pa = a ;pa ++ ;printf ( "%s\n" , * pa );return 0 ;}// 结果: at
解析:
二级指针这里用图解方式来讲解,
a指针数组,存放的是字符串,首字符地址。所以,看图就很容易了,pa++就指向数组第二个元素,内容刚好是地址,可以让%s打印。
6. (本小节最难)
#include<stdio.h>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 ;}
解析:
这个题的关键就是能否画好图,有图了指针指向就清晰了。
(1) printf("%s\n", **++cpp);
这不多说上图,清晰明了。
结果就是 NEW
(2) printf("%s\n", *--*++cpp+3);
后边+3意思是从字符串第4个字符开始打印,结果就是 ER。
(3) printf("%s\n", *cpp[-2]+3);
cpp因为前面的操作改变了地址,*cpp[-2]意思可以是 *(cpp - 2) 也就是cp首元素,如图:
结果就是 ST
(4) printf("%s\n", cpp[-1][-1]+1);
这里以二维数组来看不太容易看清,我们换种表达方式 --> *(*(cpp - 1) - 1 ) + 1 ,如图:首先找到cpp第二个地址,然后再找到c数组中的第二个元素地址,然后再找到第2个字符地址,最后在该地址开始打印。
三. 结语
到这里,本小节的内容已经结束了,希望能给大家带来收获,如果有帮助给我点个赞,你的赞将会成为博主创作的动力,最后感谢大家的浏览,如果有啥建议,欢迎大家在评论区评论。