指针笔试题,你,是否写过?

一. 前言

         本小节将会给小伙伴们分享一些关于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个字符地址,最后在该地址开始打印。

三. 结语

    到这里,本小节的内容已经结束了,希望能给大家带来收获,如果有帮助给我点个赞,你的赞将会成为博主创作的动力,最后感谢大家的浏览,如果有啥建议,欢迎大家在评论区评论。

猜你喜欢

转载自blog.csdn.net/qq_72112924/article/details/129911108