【C语言】指针的进阶(四)—— 企业笔试题解析

笔试题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;
}

【答案】在x86环境下运行

【解析】

&a是取出整个数组的地址,&a就表示整个数组,因此 &a + 1就是跳过一整个数组指向数组后方,因为这是一个数组的地址,不能够直接赋值给整型指针,所以需要将该地址强制转换为整型指针,才能给指针ptr接收,此时指针ptr就指向了数组后方。

因此*(a+1)就等于a[1]自然是2,而*(ptr-1)就是向前挪动一个整型指向5


 

 笔试题2:

struct Test
{int Num;char* pcName;short sDate;char cha[2];short sBa[4];
}*p;
//假设p 的值为0x100000。 如下表表达式的值分别为多少?
//已知,结构体Test类型的变量大小是20个字节
//0x开头的数组是16进制的数字
int main()
{p = (struct Test*)0x100000;printf("%p\n", p + 0x1);printf("%p\n", (unsigned long)p + 0x1);printf("%p\n", (unsigned int*)p + 0x1);return 0;
}

【答案】在x86环境下运行

【解析】

%p:把要打印的数以地址的形式来打印。

  • p是结构体指针,p + 1 就是跳过一个结构体的大小即20个字节,又因为%p是以16进制地址形式打印,10进制的20等于16进制的14,因此结果为00100014。
  • p是结构体指针,被强制类型转换成unsigned long,整数+1就是+1,因此结果为00100001。
  • p是结构体指针,被强制类型转换成unsigned int*,在x86环境下,只要是指针大小就为4,那么指针+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;
}

【答案】在x86环境下运行,小端存储

【解析】

该题涉及到大小端存储的问题,往期博客中有进行探讨,这里就不多赘述,如有兴趣或者不懂的可前往:点击前往

&a是取出整个数组的地址,&a就表示整个数组,因此 &a + 1就是跳过一整个数组指向数组后方,因为这是一个数组的地址,不能够直接赋值给整型指针,所以需要将该地址强制转换为整型指针,才能给指针ptr接收,此时指针ptr1就指向了数组后方。

ptr1[-1]等价于*(ptr1-1),表示ptr1向前挪动一个整型指向4,结果就为4

a被强制转换成int,即首元素地址被转换成int,整型+1就是+1。假设a的地址是0x100000,此时+1就等于0x100001,然后再强制类型转换为整型指针并赋值给ptr2。

*ptr2整型指针访问四个字节(即红框所框处),此时为内存存放的图解,需要转成真实值即0x02000000。


 

笔试题4:

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

【答案】

【解析】

此题为细节题,过程不难。需要注意的是题中的是小括号,( , )即逗号表达式。a[3][2]中实际存储的是{1,3,5}。将a[0]赋值给p指针,即p指向数组第一行地址,再通过p[0]找到第一行第一个元素即1。


 

笔试题5:

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

【答案】 

【解析】

a的类型是int (*) [5] ——— 即a指针指向一个大小为5的数组

p的类型是int (*) [4] ——— 即p指针指向一个大小为4的数组

当把a所指的地址赋值给指针p之后,a p指向同一地址,但是由于a认为自己指向的是5个元素,而p认为自己指向的是4个元素,这就会导致它们就算下标相同时访问到的内容也是不一样的,如图所示。

随着数组下标的增长,地址是由低到高的变化,并且指针和指针相减的绝对值得到的是指针之间的元素个数,而当取出p[4][2]和a[4][2]的地址之后相减,就是小地址减去大地址,得到一个负数,就是-4。

%p是打印地址,会认为内存中存储的补码就是地址,所以就是打印-4的补码

原码:10000000 00000000 00000000 00000100

反码:11111111  11111111  11111111   11111011

补码:11111111  11111111  11111111   11111100

以%p地址的形式打印补码转成16进制表示:FF FF FF FC

而-4以%d形式打印就是-4

对于原码反码补码的内容,往期博客有所提及,感兴趣的可以前往:立即前往


 

笔试题6:

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

【答案】

【解析】

  • &aa表示整个数组的地址,&aa+1跳过一整个二维数组,指向数组之后,再强制类型转换成整型指针赋值给ptr1。此时*(ptr1-1)就等于ptr1向前挪动一个整型并解引用找到10。
  • aa不是单独放在sizeof()内,因此aa表示首元素地址,aa又是二维数组,因此aa的首元素地址就是一个大小为5的数组,*(aa+1)等价于aa[1],表示aa跳过一个大小为5的数组指向下一个大小为5的数组再解引用找到该数组再赋值给整型指针ptr2。此时*(ptr2-1)就等于prt2向前挪动一个整型并解引用找到5。


 

 笔试题7:阿里巴巴笔试题

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

【答案】

【解析】

a是一个字符指针数组,每个元素的类型都为char*。

pa是一个指向char*字符指针的指针,即二级指针。

pa++即是向前跳一个char*的大小,即指向a[1]的地址,*pa就是找到a[1]指向的元素at的首地址。


 

 笔试题8:

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自减1的方法去永久改变指针指向,会导致如果一步错,就会步步错的结局,因此需要非常仔细的去画图理解。

cpp存放char**类型的数据。 【** ++cpp】,cpp先自增1,跳过一个char**类型指向下一个元素的地址,如下图。

此时再对cpp进行解引用,找到cp[1],再解引用,找到c[2]即P的地址。此时%s打印出来就是POINT

 【* -- * ++cpp + 3】,加号优先级是最低的,所以最后算。cpp先自增1跳过一个char**大小指向下一个元素的地址,如下图。

此时再对cpp进行解引用,找到的是cp[2]即指向了c+1这块空间,再自减1则指向了c这块空间,再解引用找到了c[0]即ENTER中第一个E的地址,此时+3跳过三个char,最后指向ENTER中第二个E的地址,此时用%s打印出来就是ER

*cpp[-2] + 3】等价于【* *(cpp-2)+3】。与前面的cpp自增自减不同,cpp-2只是表达式并不会改变cpp的指向。

cpp[-2]指向cp[0],再解引用找到c[3],c[3]存放的是FIRST中F的地址,此时+3跳过三个字母指向FIRST中S的地址,再用%s打印出来就是ST

【 cpp[-1][-1] + 1】等价于【*(*(cpp-1) -1) + 1】。

*(cpp-1)找到c+2,c+2再-1就是c+1的地址,再进行解引用找到NEW中N的地址,再+1找到E的地址,此时用%s打印出来就是EW

 


 到此,这几道企业笔试题就讲解完成,希望能对你们有所帮助,也欢迎大家在评论区进行讨论。

如果觉得作者写的不错,求给博主一个大大的点赞支持一下,你们的支持是我更新的最大动力!

如果觉得作者写的不错,求给博主一个大大的点赞支持一下,你们的支持是我更新的最大动力!

如果觉得作者写的不错,求给博主一个大大的点赞支持一下,你们的支持是我更新的最大动力!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/139387.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于物联网的农村地区智能微电网系统(Simulink)

💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…

Kafka 源码分析——Consumer

文章目录 前言Consumer 消费流程Consumer初始化如何选举Consumer Leader消费者分区策略Consumer拉取数据提交偏移量 前言 当生产者将消息发送到Broker时,这些消息将被存储在磁盘上。消费者是如何消费这些消息呢? Consumer 消费流程 站在源码的核心角度…

java版工程管理系统Spring Cloud+Spring Boot+Mybatis实现工程管理系统源码

工程项目管理软件(工程项目管理系统)对建设工程项目管理组织建设、项目策划决策、规划设计、施工建设到竣工交付、总结评估、运维运营,全过程、全方位的对项目进行综合管理 工程项目各模块及其功能点清单 一、系统管理 1、数据字典&am…

Gin学习记录4——Controller和中间件

一. Controller 用不同的Controller可以实现业务的分类,不同类型的请求可以共用同一套中间件 1.1 单文件Controller 几乎等同于函数封装,直接将ctrl的代码写入到一个文件里然后调用: package adminimport ("net/http""git…

FP树 高效发现频繁项集

1:a,b,c,d,e 2:a,b,c 3:e,f 4:b,c,d,e 现将其建立FP树 计算支持度 a2,b3,c3,d2,e2,f1 剔除支持度1的,再排序 b3,c3,a2,d2,e2 1:b,c,a,d,e 2:b,c,a 3:e 4:b,c…

无人机“长坡”上,谁是滚出“厚雪球”的长期主义者?

“股神”巴菲特,曾提出过“长坡厚雪”的理论: 人生就像滚雪球,重要的是发现很湿的雪和很长的坡。 运用到企业经营上,“长坡”指的是企业所布局的领域发展潜力足、空间大;而“湿雪”,指的是企业竞争力强、…

大模型应用发展的方向|代理 Agent 的兴起及其未来(下)

“ 借助LLM作为代理大脑的优势,探讨了单一代理、多代理系统和人机协作等应用场景,探讨了代理的社会行为、心理活动以及在模拟社会环境中观察新兴社会现象和人类洞见的可能性。” 01 — 造福人类:代理实践 LLM型智能代理是一种新兴的方向&…

Linux——文件系统

✅<1>主页&#xff1a;&#xff1a;我的代码爱吃辣 &#x1f4c3;<2>知识讲解&#xff1a;Linux——文件系统 ☂️<3>开发环境&#xff1a;Centos7 &#x1f4ac;<4>前言&#xff1a;上期我们了解了文件在内存中得组织方式&#xff0c;那么文件在磁盘中…

【C语言】错题本(4)

一. 题目及选项: 答案解析: 知识点: 字符型在内存中的数据存储 char类型数据在内存中的图示: unsigned char类型数据在内存中的图示: 二. 题目及选项: 答案解析: A: B: C: D: 三. 题目及选项: 答案解析: 数据在计算机中是先转换成补码,再进行运算的!

C语言自定义类型详解(1)结构体知识汇总

本篇概要 本篇主要讲述C语言结构体的相关知识&#xff0c;包括结构体的基本声明&#xff0c;结构体的匿名结构&#xff0c;结构体的自引用&#xff0c;结构体变量的定义和初始化以及结构体的内存对齐等相关知识。 文章目录 本篇概要1.结构体1.1结构体的基本声明1.2结构体的特殊…

精华回顾:Web3 前沿创新者在 DESTINATION MOON 共话未来

9 月 17 日&#xff0c;由 TinTinLand 主办的「DESTINATION MOON: Web3 Dev Summit Shanghai 2023」线下活动在上海黄浦如约而至。 本次 DESTINATION MOON 活动作为 2023 上海区块链国际周的 Side Event&#xff0c;设立了 4 场主题演讲与 3 个圆桌讨论&#xff0c;聚集了诸多…

高压放大器电源有什么作用和用途

高压放大器是一种专门用于放大高压信号的电子设备。它可以将低幅度的输入信号放大成高幅度的输出信号&#xff0c;用于驱动高压负载或处理高压信号。然而&#xff0c;高压放大器需要特定的电能来运行&#xff0c;而这就是电源的作用。 高压放大器电源的主要作用是为高压放大器提…

Linux常用命令—find命令大全

文章目录 一、find命令常用功能1、find命令的基本信息如下。2、按照文件名搜索3、按照文件大小搜索4、按照修改时间搜索5、按照权限搜索举例&#xff1a;6、按照所有者和所属组搜索7、按照文件类型搜索8、逻辑运算符 一、find命令常用功能 1、find命令的基本信息如下。 命令名…

伪原创文章生成器软件的崛起-哪个伪原创文章生成器软件好?

在当今数字化的时代&#xff0c;内容创作已经成为了无处不在的需求。不论您是个人博主、企业家还是网站管理员&#xff0c;都会面临一个共同的挑战&#xff1a;如何在互联网上脱颖而出&#xff0c;吸引更多的读者和访客。 gpt批量图文改写润色软件-147SEO gpt批量图文改写润色…

栈的简单应用(利用Stack进行四则混合运算)(JAVA)

目录 中缀表达式转后缀表达式 图解 代码实现过程&#xff1a; 完整代码&#xff1a; 利用后缀表达式求值&#xff1a; 完整代码&#xff1a; 首先我们得先了解逆波兰表达式。 中缀表达式转后缀表达式 所谓的中缀表达式其实就是我们平时写的例如&#xff1a;&#xff1…

ReadPaper论文阅读工具

之前看文献一直用的EndNote嘛&#xff0c;但是突然发现了它的一个弊端&#xff0c;就是说每次没看完退出去之后&#xff0c;下次再接着看的时候它不能保留我上一次的位置信息&#xff0c;又要重头开始翻阅&#xff0c;这让我感到很烦躁哈哈。&#xff08;当然也不知道是不是我哪…

自研多模态追踪算法 PICO 为「手柄小型化」找到新思路

作者&#xff1a;张韬、林泽一 、闻超 、赵洋 研发背景 作为头戴的追踪配件&#xff0c;VR手柄可以通过HMD&#xff08;头戴显示设备&#xff09;的inside-out光学追踪定位原理&#xff0c;计算出手柄的空间运动轨迹&#xff0c;同时结合6轴传感器实现6DoF空间定位。与此同时&a…

基于若依ruoyi-nbcio增加flowable流程待办消息的提醒,并提供右上角的红字数字提醒(六)

更多ruoyi-nbcio功能请看演示系统 gitee源代码地址 前后端代码&#xff1a; https://gitee.com/nbacheng/ruoyi-nbcio 演示地址&#xff1a;RuoYi-Nbcio后台管理系统 这个部分主要是前端方面的。 1、在Navbar.vue显示右上角的图标栏里增加一项显示消息提醒的组件 <el-…

【PyTorch攻略(2/7)】 加载数据集

一、说明 PyTorch提供了两个数据原语&#xff1a;torch.utils.data.DataLoader和torch.utils.data.Dataset&#xff0c;允许您使用预加载的数据集以及您自己的数据。数据集存储样本及其相应的标签&#xff0c;DataLoader 围绕数据集包装一个可迭代对象&#xff0c;以便轻松访问…

c++STL案列一评委打分

案例描述 有5名选手:选手ABCDE&#xff0c;10个评委分别对每一名选手打分&#xff0c;去除最高分&#xff0c;去除评委中最低分&#xff0c;取平均分 实现步骤 1.创建五名选手&#xff0c;放到vector中 2.遍历vector容器&#xff0c;取出来每一个选手&#xff0c;执行for循环…