指针篇(7)- 指针运算笔试题(阿里巴巴)

目录

  • 一、指针运算笔试题解析
    • 3.1 题目1:
    • 3.2 题目2:
    • 3.3 指针3:
    • 3.4 题目4:
    • 3.5 题目5:
    • 3.6 题目6:
    • 3.7 题目7:
  • 总结


一、指针运算笔试题解析

3.1 题目1:

#include<stdio.h>
int main()
{int a[5] = { 1,2,3,4,5 };int* ptr = (int*)(&a + 1);printf("%d %d", *(a + 1), *(ptr - 1));return 0;
}

程序的运行结果是什么?
结合这个程序的内存布局来讲
在这里插入图片描述
这里把int(*)[5]类型的数组指针强制类型转换为int *类型赋值给ptr,因为类型一样才可以赋值,ptr是int *型指针,int *指针减1,向前挪动一个整型,所以 *(ptr - 1)打印结果是5。另一个打印原理很简单,看了我指针6前面的原理讲解就懂了。
在这里插入图片描述

3.2 题目2:

在这里插入图片描述
该结构体在x86环境下,大小确实为20个字节,在x64下就不是了。
这里结构体类型加了一个*,这是结构体指针类型,结构体指针创建了个变量叫p,p里有地址,0x100000是个整数,把整数赋给结构体指针,要强制类型转换。

第一个printf:指针加减整数与指针类型有关,结构体指针加1跳过一个结构体,一个结构体20个字节,这是16进制,也就是0x100014。只有指针变量+1,才可以说加几个字节。
第二个printf:这里p本是指针变量,p被强制类型转换为unsigned long,无符号长整型,整数类型,整数加1就是加1,也就是0x100001.
第三个printf:p被强制类型转换为unsigned int*,这时加1,跳过一个无符号整型,4个字节。这时地址是0x100004,这时用%p打印在x86环境下要打印够8个16进制位,32个比特位,前面补两个0,%p不打印0x。

3.3 指针3:

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

依据这串代码你所想的结果是什么呢?是不是0呢?而且所设想的初始化情况是不是这样
在这里插入图片描述

特别要注意:(0, 1)这是一个逗号表达式。在C语言中,逗号运算符会先对左边的操作数求值,然后直接丢弃这个值,最终返回右边操作数的值。

进监视看初始化情况也确实如此:
在这里插入图片描述
所以该数组的初始化结果如图:
在这里插入图片描述
一般情况的初始化要使用大括号的

int a[3][2] = { {0, 1}, {2, 3}, {4, 5} };

在这里插入图片描述
所以改代码的输出结果是1
在这里插入图片描述

3.4 题目4:

在这里插入图片描述

*(ptr1 - 1)

这里第一个打印没啥好说的,直接说第二个* (ptr2 - 1),aa数组名表示首元素地址,因为是二维数组,所以aa是第一行的地址,(aa + 1)是第二行一维数组的地址,* (aa + 1)拿到第二行整个数组,相当于数组名,aa[1]数组名又相当于首元素地址。
补充一下:这里(*(aa+1))指向6,6的地址已经是整型地址,这里也不需要强制类型转换了。
打印结果:
在这里插入图片描述

3.5 题目5:

在这里插入图片描述
这里把a的地址赋给p,两者类型不同,但p其实还是可以接收的,只不过会报警告。类似于下面的代码

int num = 10;
int* p1 = &num;
char* p2 = &num;//类型差异

由于p指向的数组是4个元素,所以p接收的是第一个黑框,这里p也访问的是二维数组。

注意:这里要区分p和a的角度,这些黑框都是以p为单位+1,+2指向的地址。地址减地址,得到的是两个地址之间的元素个数。且随着数组下标的增长,地址是由低到高变化的。

红块是&p[4][2],绿块是&a[4][2],打印的两个值都是小地址减大地址,得到的是一个负数(-4)。

打印的时候
%d - 按照10进制的形式,打印有符号的整数。
%d认为内存中存放的是有符号整数的补码。

%p - 打印地址的
%p认为内存中存放的补码就是地址
%p打印地址是以16进制的形式打印的

//假设环境是x86环境,程序输出的结果是啥?
#include <stdio.h>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]);//-4//10000000 00000000 00000000 00000100 - 原码//11111111 11111111 11111111 11111011 - 反码//11111111 11111111 11111111 11111100 - 补码//FF       FF       FF       FCreturn 0;
}

在这里插入图片描述

3.6 题目6:

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

这里创建了一个char* 的指针数组,数组的每个元素为char* ,是否每个元素对应一个字符串呢?
实则不然

char* p={“abcdef"};

这个代码p里存放的是字符串的首字符地址,对应过来,这里char* 的指针数组,每个元素存放一个字符串首字符的地址,a数组的每个元素都为char* 类型。

结合图来看:
在这里插入图片描述

pa是一个二级指针,char** pa = a相当于把一个一级指针的地址放到二级指针变量里去了,pa++跳过一个char* 的元素,指向第二个元素。* pa拿到at里a的地址,a的地址交给%s打印,有了起始地址向后打印,遇到\0停下来。

3.7 题目7:

接下来的题目是这一章里最难的一题了

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

先看第一个printf内存布局图:
在这里插入图片描述

printf("%s\n", **++cpp);

++cpp指向c+2的地址,* ++cpp拿出c+2的地址,c+2的地址又指向c
数组里P的地址,再解引用拿到P的地址,所以第一个printf打印出POINT。

第二个printf内存布局图:
在这里插入图片描述

printf("%s\n", *-- * ++cpp + 3);

前面++cpp已经把cpp的指向改了,cp改为cp+1。这里++的优先级高于加法运算符,这里++cpp指向c+1的地址,* ++cpp拿到c+1的地址,也可以理解为拿到c+1这个元素再- -,c+1变c,这时就只想了c数组里E的地址,再解引用拿到E的地址,+3拿到ENTER\0里第二个E的地址,此时打印ER。

第三个printf内存布局图:
在这里插入图片描述

printf("%s\n", *cpp[-2] + 3);

*cpp[-2]不好理解拆解换算一下,cpp[-2]就是cpp+(-2)再解引用,再把原来的 * 加上就是 * * (cpp-2),再+3。
在这里插入图片描述
cpp-2就是cp+1+1-2,即cp。意思为cpp里的变量值-2,cp为c+3的地址,解引用拿到c+3的地址,c+3指向指向c数组里的F,再解引用拿到F的地址,+3指向S,打印结果为ST。

第四个printf内存布局图:
在这里插入图片描述

printf("%s\n", cpp[-1][-1] + 1);

拆解换算之后如图:
在这里插入图片描述

这里cpp里的值没变,只有加加,减减才会改变里面的值,依旧是cp+2,(cpp-1)之后变为cp+1,相当于指向c+2处的地址,第一次解引用拿到c
+2的地址,c+2指向P处位置的地址,再-1,指向N处,解引用拿到N的地址,+1指向N后E的地址,打印结果为EW。

总结

以上就是笔试题的全部内容了,不得不说有些笔试题确实出的非常刁钻,但总的来说还是考察指针地址的理解,还是挺有意思的。喜欢的靓仔靓女们不要忘记一键三连支持一下~

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

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

相关文章

homebrew的一些常用方法

前言 因本人工作换到mac电脑&#xff0c;对包管理器homebrew的需求增加&#xff0c;因此将一些常用命令做如下记录&#xff0c;本博客主要用作记录用。 官网 macOS&#xff08;或 Linux&#xff09;缺失的软件包的管理器 — Homebrew 常用命令 如果脚本因网络问题无法下载…

【Python面试题】Python面试之基础知识常见面试题3-汇总篇(精选30个)

目录专栏导读前言1. 字典的内存管理机制是什么&#xff1f;2. 列表的内存管理机制是什么&#xff1f;3. 元组和列表的区别4. 字符串插值的方法5. 闭包、装饰器的原理闭包&#xff08;Closure&#xff09;装饰器&#xff08;Decorator&#xff09;6. map、filter的区别7. range(…

【免费.NET方案】CSV到PDF与DataTable的快速转换

CSV作为轻量级数据载体&#xff0c;在数据传输中占比超过70%。但其原生格式存在三大痛点&#xff1a; 可视化缺陷&#xff1a;无法直接生成可打印的报表结构限制&#xff1a;缺乏数据类型定义和关系约束安全风险&#xff1a;易被意外修改导致数据失真 因此&#xff0c;我们常…

connect的断线重连

connect的短线重连 客户端代码的编写服务器代码的编写总结 客户端代码的编写 #include <iostream> #include <string> #include <cstring> #include <cstdlib> #include <unistd.h> #include <sys/types.h> #include <sys/socket.h>…

通过观看数百个外科手术视频讲座来学习多模态表征|文献速递-最新论文分享

Title题目Learning multi-modal representations by watching hundreds of surgical video lectures通过观看数百个外科手术视频讲座来学习多模态表征01文献速递介绍外科计算机视觉领域的最新进展&#xff0c;已开始为手术室&#xff08;OR&#xff09;的新一代人工智能辅助支…

微信小程序如何实现再多个页面共享数据

在微信小程序中&#xff0c;实现多个页面共享数据有以下几种常用方式&#xff0c;根据场景选择最适合的方案&#xff1a; 全局变量&#xff08;App.js&#xff09; 适用场景&#xff1a;简单数据共享&#xff08;非响应式&#xff09; 实现方式&#xff1a; javascript // ap…

PCIE5.0 TAG说明(ima回答)

在PCIe 5.0规范中&#xff0c;TLP&#xff08;Transaction Layer Packet&#xff09;报文的Tag字段用于标识和管理事务。以下是关于Tag的生成和使用规则和定义的详细描述&#xff1a; Tag字段的定义 Tag字段&#xff1a;位于TLP报文的Header中&#xff0c;占用8位&#xff08…

Type-C PD快充协议智能芯片S312L详解

1. 芯片概述 S312L 是一款智能Type-C PD协议触发芯片&#xff0c;支持**PD3.0&#xff08;含PPS&#xff09;**及多种A口快充协议&#xff08;如QC/PE等&#xff09;&#xff0c;可自动识别并申请5V/9V/12V电压&#xff0c;适用于快充适配器、移动电源等场景。 核心优势&…

stm32学到什么程度可以找工作?

我重新为你写一篇更加详细深入的回答&#xff1a; STM32学到什么程度可以找工作&#xff1f;一个十年老兵的血泪史 写在前面的话&#xff1a;这些年踩过的坑&#xff0c;都是血淋淋的教训 刚看到这个问题&#xff0c;我就想起了2014年那个炎热的夏天。 当时我刚从厦门某马离…

基于 Elasticsearch 实现地图点聚合

在地图类应用中&#xff0c;当需要展示大量地理兴趣点时&#xff0c;直接将所有点渲染在地图上会导致视觉混乱&#xff0c;影响用户体验。为此&#xff0c;我基于 Elasticsearch 提供的 geotile_grid 和 geo_bounding_box 查询能力&#xff0c;实现了一套高效的 POI 聚合展示方…

【Prometheus 】通过 Pushgateway 上报指标数据

Prometheus 是目前最流行的开源监控系统之一&#xff0c;其拉取&#xff08;pull&#xff09;模型非常适合服务发现和静态目标的监控。然而&#xff0c;在某些场景下&#xff0c;例如短生命周期任务、批处理作业或无法暴露 HTTP 接口的服务&#xff0c;传统的拉取方式并不适用。…

服务器 - - QPS与TPS介绍

1、QPS&#xff08;Queries Per Second 每秒查询数&#xff09; 定义&#xff1a;常用于表示每秒的请求次数&#xff0c;衡量接口请求、数据库查询等动作的吞吐量&#xff08;单位时间内处理的数据量&#xff09; 计算&#xff1a;总请求数/请求时间&#xff0c;如&#xff1…

Cot2:思维链提示激发大型语言模型的推理能力

摘要 我们探讨了生成思维链——一系列中间推理步骤——如何显著提升大型语言模型执行复杂推理的能力。特别地&#xff0c;我们展示了在足够大的语言模型中&#xff0c;这种推理能力如何通过一种简单的方法——思维链提示&#xff08;chain-of-thought prompting&#xff09;自…

go交易数据后端

地址 https://gitee.com/EEPPEE_admin/go-stock-line-trading-datahttps://github.com/jerryshell/midas 需求 为了替代rust后端爬虫端: 爬取东方财富数据到index-data目录server端: 项目主要内容 todo 替代https://github.com/jerryshell/midas的前端量化概念性理解扩展: 存储…

灵巧手概览

第一章 灵巧手的技术演进与核心价值 1.1 技术演进的五个阶段 仿生学启蒙阶段&#xff08;1960-1980&#xff09; 1968年斯坦福大学首台3自由度机械夹爪标志机器人操作技术开端&#xff0c;1973年MIT提出"仿生手"概念&#xff0c;但受限于材料和控制技术&#xff0c;…

在设计提示词(Prompt)时,关于信息位置的安排z怎么 结合模型特性和任务目标

在设计提示词(Prompt)时,关于信息位置的安排z怎么 结合模型特性和任务目标 在设计提示词(Prompt)时,关于信息位置的安排确实需要结合模型特性和任务目标。从自注意力机制的原理及应用场景来看,关键信息的位置选择需遵循以下启示,并结合具体场景灵活调整: 一、核心启示…

七、性能优化

目录 1. 如何检测Flutter应用的性能问题&#xff1f;2. 什么是重绘边界&#xff08;Repaint Boundary&#xff09;&#xff1f;3. 如何避免不必要的重建&#xff1f;4. const 构造函数在优化中起什么作用&#xff1f;5. 如何优化长列表的性能&#xff1f;6. 如何减少应用启动时…

Webpack优化详解

Webpack 5提供了一系列工具和功能,可以在本地开发和线上构建过程中进行优化,以提高开发效率和构建性能。 1. 本地开发优化 1.1. 开启模块热替换(HMR) 模块热替换可以在不刷新整个页面的情况下更新模块,提高开发效率。 const webpack = require(webpack);module.export…

latency 对功耗的影响

文章目录 1、Connection Interval(连接间隔) vs. Latency(从机延迟)2、为什么不能完全依赖 Connection Interval?3、什么时候可以不用 Latency?4、如何正确配置?5、结论调节连接间隔(Connection Interval)确实可以直接影响通信频率和功耗,但 Latency(从机延迟)仍然…

10分钟搭建 PHP 开发环境教程

下载、安装 Xserver 下载 php 过程中如果提示需要安装 vc 运行环境&#xff0c;按照引导下载安装即可 安装 nginx 安装 Mysql 支持多个版本同时安装 下载 php 过程中如果提示需要安装 vc 运行环境&#xff0c;按照引导下载安装即可mysql 默认用户名为 root&#xff0c;默认密…