指针面试笔试题练习
创始人
2024-05-28 23:10:54
0

在这里插入图片描述

前言

🎈个人主页:🎈 :✨✨✨初阶牛✨✨✨
🐻推荐专栏: 🍔🍟🌯 c语言进阶
🔑个人信条: 🌵知行合一
🍉本篇简介:>:介绍c语言中有关指针更深层的知识.
金句分享:

✨星光不问赶路人,✨
✨时光不负有心人。✨

目录

  • 前言
  • 笔试题1
    • 文字解释1:
    • 图解1:
  • 笔试题2
    • 文字解释2:
  • 笔试题3
    • 文字解释3:
    • 图解3:
  • 笔试题4
    • 文字解释4:
  • 笔试题5
    • 文字解释5:
    • 图解5:
  • 笔试题6
    • 图解6:
  • 笔试题7
  • 笔试题8(难度提升)
    • 分析1: ** ++cpp
      • 分步动态图解1:
    • 分析2:*-- * ++cpp + 3
      • 分步动态图解2:
    • 分析3:*cpp[-2] + 3
      • 分步动态图解3:
    • 分析4:cpp[-1][-1] + 1
      • 分步动态图解4:

笔试题1

题目1:

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

文字解释1:

a是数组名,类型为int[5],则&a类型为int(*)[5],当&a+1时,一次会跳过5个整形数据,则指向a数组的最后一个元素的后一个位置,ptr - 1刚好指向a数组的最后一个元素,解引用(星号)就会得到整形数字5.
a+1表示数组的第二个元素,所以解引用得到整形数字2.

图解1:

在这里插入图片描述

笔试题2

不了解指针运算的可以点击这里哦!
[传送门]
考点:指针+1,跳过的步长

题目2:

#include 
//已知结构体Test的大小是20字节
struct Test
{int Num;char* pcName;short sDate;char cha[2];short sBa[4];
}*p;
int main()
{p = (struct Test*)0x100000;//假设p 的值为0x100000。printf("%p\n", p + 0x1);//0x100020printf("%p\n", (unsigned long)p + 0x1);//0x10printf("%p\n", (unsigned int*)p + 0x1);return 0;
}

在这里插入图片描述
运行结果:

00100014
00100001
00100004

文字解释2:

p + 0x1:
因为p是一个结构体指针,结构体的大小是20个字节,所以p+0x1会跳过20个字节,20转化为16进制表示是14.

(unsigned long)p + 0x1:
这里需要注意的是,这里将p强制转化为无符号长整形,并不是无符号长整形指针,所以,+0x1只是正常的+1,就好比1+1=2,就只是变量之间的正常+1.

(unsigned int*)p + 0x1
将p指针强制转化为无符号整形指针,因为无符号整形是四个字节,则+0x1会跳过四个字节,转化为16进制4.

笔试题3

题目3:
环境:x86 小端环境

#include 
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,2000000

文字解释3:

ptr1
因为&a + 1表示跳过a数组,指向a数组最后一个元素的后一个位置.
ptr1[-1]等价于 *(ptr-1),即解引用得到数组的最后一个元素4.

ptr2:需要注意的是,向后偏移了一个字节.
(int)a + 1,表示将a强制转化为int整形,整形+1就是正常的+1,则会向后偏移一个字节,
(int*)((int)a + 1)再强制转化为整形指针,在小端存储模式下,会从首元素1(占四个字节)的第二个字节开始,向后读取四个字节(红色框框).这时按16进制打印出来就是2000000了.

图解3:

在这里插入图片描述

笔试题4

#include 
int main()
{int a[3][2] = { (0, 1), (2, 3), (4, 5) };int* p;p = a[0];printf("%d", p[0]);return 0;
}

运行结果:

1

文字解释4:

是不是感觉很奇怪,不应该是0吗?
a[0]表示二维数组的第一行的数组名,那么p[0]就等价于a[0][0],就是0呀.
实际本题考察重点是在逗号表达式.
? ? ?
这才是二维数组的初始化:用的是{}
int a[3][2] = { {0, 1 }, {2, 3}, {4, 5} };
而上面用的是(),则编译器会认为是逗号表达式,只保留后面的结果.
等价于:
int a[3][2] = { (0, 1), (2, 3), (4, 5) }; ====== int a[3][2] = { 1, 3, 5 };
故二维数组的初始化结果是
1 3
5 0
0 0
第一行第一个元素是1.做题要仔细哦,掉坑里了.

笔试题5

题目:

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

文字解释5:

a是二维数组的数组名,类型是int ()[5],一次跳过五个整形
p是一个数组指针,类型是int(
)[4],一次跳过四个整形,
a[4][2]与p[4][2]之间差了4个字节,即&p[4][2] - &a[4][2]=-4;
-4按"%p"形式打印.会认为内存中的数据是内存.-4在内存中是按补码存的.

-4
1000 0000 0000 0000 0000 0000 0000 0100原码
1111 1111 1111 1111 1111 1111 1111 1011反码
1111 1111 1111 1111 1111 1111 1111 1100补码
转化为16进制表示地址后:F F F F F F F C

图解5:

在这里插入图片描述

笔试题6

题目:

#include 
int main()
{int aa[2][5] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };int* ptr1 = (int*)(&aa + 1);int* ptr2 = (int*)(*(aa + 1));printf("%d,%d", *(ptr1 - 1), *(ptr2 - 1));return 0;
}

解释:
看图理解方便(偷个懒)

图解6:

在这里插入图片描述

笔试题7

题目:

#include 
int main()
{char* a[] = { "work","at","alibaba" };char** pa = a;pa++;printf("%s\n", *pa);return 0;
}

在这里插入图片描述
运行结果:

at

解释:

a是一个字符指针,类型是char*,a+1会跳过一个char类型.
pa是一个二级指针,类型是char**,pa+1会跳过一个char*.即指向数组的第二行,%s从该地址处向后打印直到遇到’\0’.

动图解析:

在这里插入图片描述

笔试题8(难度提升)

#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);			//1printf("%s\n", *-- * ++cpp + 3);	//2printf("%s\n", *cpp[-2] + 3);		//3printf("%s\n", cpp[-1][-1] + 1);	//4return 0;
}

在这里插入图片描述
运行结果:

POINT
ER
ST
EW

解释分析:
需要注意的是,当进行自增(++)或者自减(–)时,会真正改变指针的值,从而影响后面的语句.而加减整数或者访问元素([ ])并不会改变指针本身.并不会对后面的语句造成影响.

c是一个字符指针,+1会跳过一个字符(1字节).
cp是一个指向一级字符指针二级指针,+1可以跳过一个char*类型指针.
cpp是一个指向cp的三级指针,+1会跳过一个二级指针.

分析1: ** ++cpp

原始状态图:
在这里插入图片描述

++cpp会跳过一个二级指针,并且是真正改变cpp指针的内容,
cpp会指向cp的第二个元素,c+2
*++cpp表示得到c+2的地址
**++cpp表示得到c+2的值,即P的地址,按%s打印会得到,POINT.

分步动态图解1:

在这里插入图片描述

分析2:*-- * ++cpp + 3

注意!!!
cpp由于1的改变,现在指向的是c+2.

原始图2:
在这里插入图片描述

++cpp会使cpp指向c+1(cp的第二个元素).
*++cpp得到c+1的地址
- - *++cpp表示c+1的地址–,会会指向c
*-- * ++cpp 会得到c的地址
*-- * ++cpp + 3表示指向E
按%s打印会打印ER.

分步动态图解2:

在这里插入图片描述

分析3:*cpp[-2] + 3

注意!!!
因为2的改变,此时cpp指向的是c+1.

图三原始图:
在这里插入图片描述

cpp[-2]等价于*(cpp-2),表示访问cpp指向的元素,往前找两个位置,即cp的第一个元素,c+3,
*cpp[-2]解引用得到c+3的地址.
*cpp[-2] + 3,表示指向c+3的第3个字符.
按%s打印,结果为ST

分步动态图解3:

在这里插入图片描述

分析4:cpp[-1][-1] + 1

注意!!!
3只是[-2]访问,并没有改变cpp本身.
原始图四:(与图三一样)
在这里插入图片描述

cpp[-1]等价于*(cpp-1),表示访问cpp指向的内容的前一个,即c+2(cp的第二个元素).
cpp[-1][-1]表示访问c+2地址的前一个,即N地址处.
cpp[-1][-1] + 1表示从N地址的下一个地址,E开始.
按%s打印是EW

分步动态图解4:

在这里插入图片描述
这次的指针面试题练习就讲到这里,希望对各位有所帮助.
886.
在这里插入图片描述

相关内容

热门资讯

【NI Multisim 14...   目录 序言 一、工具栏 🍊1.“标准”工具栏 🍊 2.视图工具...
银河麒麟V10SP1高级服务器... 银河麒麟高级服务器操作系统简介: 银河麒麟高级服务器操作系统V10是针对企业级关键业务...
不能访问光猫的的管理页面 光猫是现代家庭宽带网络的重要组成部分,它可以提供高速稳定的网络连接。但是,有时候我们会遇到不能访问光...
AWSECS:访问外部网络时出... 如果您在AWS ECS中部署了应用程序,并且该应用程序需要访问外部网络,但是无法正常访问,可能是因为...
Android|无法访问或保存... 这个问题可能是由于权限设置不正确导致的。您需要在应用程序清单文件中添加以下代码来请求适当的权限:此外...
北信源内网安全管理卸载 北信源内网安全管理是一款网络安全管理软件,主要用于保护内网安全。在日常使用过程中,卸载该软件是一种常...
AWSElasticBeans... 在Dockerfile中手动配置nginx反向代理。例如,在Dockerfile中添加以下代码:FR...
AsusVivobook无法开... 首先,我们可以尝试重置BIOS(Basic Input/Output System)来解决这个问题。...
ASM贪吃蛇游戏-解决错误的问... 要解决ASM贪吃蛇游戏中的错误问题,你可以按照以下步骤进行:首先,确定错误的具体表现和问题所在。在贪...
月入8000+的steam搬砖... 大家好,我是阿阳 今天要给大家介绍的是 steam 游戏搬砖项目,目前...