数组、指针练习题及解析(含笔试题目讲解)(二)

news2024/10/7 3:15:07

 接上文,我们继续笔试题目讲解。


目录

笔试题3

笔试题4

笔试题5

笔试题6

笔试题7

面试题8

总结


笔试题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);//0x00 00 00 04    0x02 00 00 00
  return 0;
}

 程序分析:

这道题在小端存储的计算机上运行的前提下进行讲解。大小端介绍详见前几期博客的讲解连接如下:数据在内存中的存储_清水加冰的博客-CSDN博客

已知计算机为小端存储,那数组a在内存中存储情况就如下图所示:

 1转化为16进制就是0x00 00 00 01,在小端机器中存储方式如上图所示。

 ptr1为(int*)(&a+1)

 &a为int (*)[4]类型,&a+1也是int (*)[4]类型,(int*)(&a+1)就是将&a+1的类型强制类型转换为int*类型(指针类型不同,+1-1所跳过的空间大小不同)。

 那ptr1[-1]就等价于:*(ptr1-1),那ptr1-1所指向位置也就是元素4,如下图:

 在解引用输出就是0x4(%x输出16进制)。

ptr2 = (int *)((int)a + 1),a是数组首元素地址,将a强制类型转换为int类型,我们先假设a的地址为0x0014ff20,转换为整形,还是0x0014ff20,只不过这里的16进制表示的是数字,那(int)a + 1也就是正常的整数相加,(int)a + 1=0x0014ff21,再将(int)a + 1转换为int*类型,那此时(int)a + 1,也就是a数组首元素地址跳过了一个字节的空间。如下图所示:

 然后输出解引用的值,(int)a + 1从整形又被转换为int*类型的指针,整形指针解引用需要4个字节的空间,于是就从(int)a + 1指向的位置向后找4个字节空间的数据,转换为整形。

 即00 00 00 02,又因为存储时是小端存储,所以取出时的顺序应该是:02 00 00 00,转换16进制也是0x02 00 00 00

笔试题4

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

分析:

a是一个二维数组,进行了初始化,但它实质上只初始化了三个值,即1,3,5。这里需要注意,初始化使用的是逗号表达式,如果想一行一行初始化应该用{0,1}。所以这里有坑需要看仔细。

 

 

 整形指针变量p=a[0],一般情况下,我们可以把a[0]理解为二维数组的第一行,但这里注意p是一个整形指针,并且赋值的时候没有&a[0],这里的a[0]就相当于是第一行数组的数组名,指向的是数组a[0][0]的地址。p[0]等价于*(p+0),也就是*p,所以结果是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]);//0xFFFFFFFC     -4
  return 0;
}

分析:

p是一个int(*)[4];类型的指针,p = a,a是一个5行5列的二维数组,那a就是第一行的地址,a是int(*)[5]类型,在赋值时会发生类型转换。我们注意,a走一步是5个整数空间,p走一步是4个整形空间。

 我们来看一下p[4][2]的位置,a[4][2]的位置。

 它们之间相差了4个字节。我们知道数组在存储地址时是从低地址到高地址,那我们就可以知道&p[4][2] - &a[4][2]以%d的形式输出就是一个-4。

负4的二进制序列为:

原码:10000000000000000000000000000100

反码:11111111111111111111111111111011

补码:1111 1111 1111 1111 1111 1111 1111 1100

 当我们以%p(输出地址)的形式打印时,计算机就会将补码当作地址输出

1111 1111 1111 1111 1111 1111 1111 1100

   F      F       F      F      F      F     F      C

 也就是0xFFFFFFFC。

笔试题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));//10    5
  return 0;
}

分析:

aa是一个二维数组,&aa取出的是二维数组的地址,&aa+1跳过的是整个二维数组。aa是二维数组首元素的地址,aa+1跳过的是5个整形空间。并且它们都被强制类型转换为int*类型。

 ptr1 - 1和ptr2-1也就是ptr1和ptr2向前跳过4个字节(一个整形空间),所以*(ptr1 - 1), *(ptr2 - 1)也就是10和5。

笔试题7

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

分析:

单个字符串时我们可以这样写:char *p=“abcdef”,那当多个字符串呢?

上述题目中就是一个字符指针数组。

a是一个字符指针数组,a[0]存放的是w的地址,a[1]存放的是a(at)的地址,a[2]存放的是a(alibaba)的地址。

char**pa = a;,pa是一个二级指针,pa指向的是a[0],现在pa++之后,pa指向的就是a[1]。

 *pa就是a[0],指向的是at中a的地址,而%s输出时需要一个字符串地址才能输出,所以输出结果是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);//POINT
printf("%s\n", *--*++cpp+3);//ER
printf("%s\n", *cpp[-2]+3);//ST
printf("%s\n", cpp[-1][-1]+1);//EW
return 0;
}

这道题于上到题目类似,但这道题难度更高一些。

分析:

我们先根据三个变量的初始化画出它们的关系图:

 **++cpp,先是cpp++,此时cpp指向的就是cp[1],**就是两次解引用,第一次解引用是cp[1],再解一次引用就是C[2],C[2]是POINT中P的地址,那么输出的就是POINT

*--*++cpp+3,这个看起来很复杂,也间接的考察了优先级,先是++cpp,由于cpp经过了一次++操作,所以这里++操作之后cpp指向的是cp[2],再解引用就是cp[2],然后再对cp[2]进行--操作,这时cp[2]指向的就是C[0],解引用就是ENTER中E的地址,再+3,指向的就是第二个E,输出也就是ER

*cpp[-2]+3,cpp[-2]等价于*(cpp-2),那么*cpp[-2]+3也就可以写成**(cpp-2)+3,这里我们是先进行cpp-2操作,减2之前,cpp指向的是cp[2],cpp-2指向的就是cp[0],进行一次解引用是cp[0]也就是C+3,在解引用一次就是FIRST中F的地址,在+3,就是S的地址,那么输出就是ST

 cpp[-1][-1]+1,这里我们在次转换一下,转换为*(*(cpp-1)-1)+1,首先看cpp,在上一个操作中cpp并没有进行++或--操作,所以此时cpp指向的依然是cp[2],cpp-1指向的就是cp[1],解引用就是cp[1](C+2),然后是*(cp[1]-1)+1,cp-1指向的是C[1],解引用后就是NEW中N的地址,+1指向的就是E的地址,所以最终输出是EW


总结

好了本期内容到此结束,希望这些内容能够对您的编程之路有所帮助。最后,感谢您阅读本文并参与博主提供的练习题。如果您有任何疑问或建议,请随时在评论区留言,博主将尽快回复您。感谢阅读!

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

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

相关文章

postman 携带时间戳及md5加密预处理

// 获取全局变量 uid postman.getGlobalVariable(“uid”) sid postman.getGlobalVariable(“sid”) //设置当前时间戳 postman.setGlobalVariable(“time”,Math.round(new Date().getTime())); time postman.getGlobalVariable(‘time’) //设置KEY_WORD为全局变量 post…

C# SolidWorks 二次开发 -从零开始创建一个插件(1)

学习内容:从零开始定制一个SolidWorks插件 作为了一个职业的二次开发人员&#xff0c;我曾经创建插件"无数"。但从未像今天这篇文章这样&#xff0c;从空项目开始&#xff0c;之前的文章中我有介绍&#xff0c;要么使用SolidWorks API模板&#xff0c;要么使用了第三…

小马哥JAVA实战营-JDBC

小马哥是一个非常牛逼的技术大牛&#xff0c;最近在看他的课&#xff0c;感兴趣也可以关注一波小马哥&#xff08;不是引流&#xff0c;是真的很推荐&#xff09;&#xff1a; 小马哥B站 JDBC规范文档 jdbc规范文档下载链接 JDBC的主要特征 面向数据表行列编程驱动程序需要…

《3.linux应用编程和网络编程-第8部分-3.8.网络基础》 3.8.1.网络通信概述 3.8.3.网络通信基础知识2

进程间通信&#xff1a; 管道 、 信号量、 共享内存&#xff0c; 技术多&#xff0c;操作麻烦 线程就是解决 进程间 通信 麻烦的事情&#xff0c;这是线程的 优势 3.8.1.网络通信概述 3.8.1.1、从进程间通信说起&#xff1a;网络域套接字socket&#xff0c;网络通信其实就是位…

2023.7月最新版idea安装Jrebel实现热部署,可解决后端启动等待时间过长问题

2023.7最新版idea热部署配置 一 下载jrebel插件二 激活我使用的方法 三 配置方式1 设置自动编译2 设置 compiler.automake.allow.when.app.running3 勾选项目&#xff0c;然后以Rebel方式启动 4 Settings查看Activation情况四 报错解决1 启动失败 2 端口被占用 五 总结 一 下载…

JS 的 new 到底是干什么的?

大部分讲 new 的文章会从面向对象的思路讲起&#xff0c;但是我始终认为&#xff0c;在解释一个事物的时候&#xff0c;不应该引入另一个更复杂的事物。 今天我从「省代码」的角度来讲 new。 --------------------------- 想象我们在制作一个策略类战争游戏&#xff0c;玩家…

网络编程【网络编程基本概念、 网络通信协议、IP地址 、 TCP协议和UDP协议】(一)-全面详解(学习总结---从入门到深化)

目录 网络编程基本概念 网络通信协议 IP地址 TCP协议和UDP协议 网络编程基本概念 计算机网络 计算机网络是指将地理位置不同的具有独立功能的多台计算机及其 外部设备&#xff0c;通过通信线路连接起来&#xff0c;在网络操作系统&#xff0c;网络管理软 件及网络通信协议的…

echarts图表进度条类型图

1、实现效果 左边是类别、数量&#xff0c;中间类似于进度条&#xff0c;右边是所占百分比 2、实现思路 x轴不显示&#xff0c;y轴的axisLabel用富文本&#xff0c;显示机器与台数&#xff1b;图表有两个数据组&#xff0c;分别用蓝色和灰色表示&#xff0c;两个柱子重合&…

Jmeter beanshell编程实例

目录 1、引言 2、需求 3、BeanShell实现 3.1、原始单元测试的java代码&#xff1a; 3.2、调用的RSAUtil原始方法&#xff1a; 3.3、使用BeanShell预处理器实现报文加密&#xff1a; 库导入部分&#xff1a; JSON报文组装&#xff1a; RSA加密&#xff1a; 3.4、取样器…

【C语言】指针进化:传参与函数(2)

莫道君行早&#xff0c;更有早行人。— 出自《增广贤文上集》 解释&#xff1a;别说你出发的早&#xff0c;还有比你更早的人。 这篇博客我们将会深入的理解数组传参和函数指针等指针&#xff0c;是非常重要的内容&#xff0c;学好这部分才能算真正学懂C语言。 目录 一维数组传…

【网络】socket——预备知识 | 套接字 | UDP网络通信

&#x1f431;作者&#xff1a;一只大喵咪1201 &#x1f431;专栏&#xff1a;《网络》 &#x1f525;格言&#xff1a;你只管努力&#xff0c;剩下的交给时间&#xff01; 在前面本喵对网络的整体轮廓做了一个大概的介绍&#xff0c;比如分层&#xff0c;协议等等内容&#x…

UFS 14 - UFS RPMB安全读写命令

UFS 14 - UFS RPMB安全读写命令 1 SECURITY PROTOCOL IN/OUT Commands1.1 CDB format of SECURITY PROTOCOL IN/OUT commands1.2 Supported security protocols list description1.3 Certificate data description 2 CDB format of SECURITY PROTOCOL IN/OUT commands demo2.1 …

Spring Boot原理分析(一):项目启动流程、自动装配

文章目录 一、项目启动流程二、SpringBootApplication.java源码解析1.准备工作2.源码3.自定义注解4.组合注解5.注解ComponentScan过滤器 6.注解SpringBootConfigurationConfiguration 7.注解EnableAutoConfiguration&#xff08;1&#xff09;Spring手动装配使用XML配置文件使用…

Nerf论文阅读笔记Neuralangelo: High-Fidelity Neural Surface Reconstruction

Neuralangelo&#xff1a;高保真神经表面重建 公众号&#xff1a;AI知识物语&#xff1b;B站暂定&#xff1b;知乎同名 视频入门介绍可以参考 B站——CVPR 2023最新工作&#xff01;Neuralangelo&#xff1a;高保真Nerf表面重建 https://www.bilibili.com/video/BV1Ju411W7…

杨氏矩阵,字符串左旋,字符串旋转结果题目解析

杨氏矩阵 题目要求:有一个数字矩阵&#xff0c;矩阵的每行从左到右是递增的&#xff0c;矩阵从上到下是递增的&#xff0c;请编写程序在这样的矩阵中查找某个数字是否存在。 示例 分析:我们仔细分析&#xff0c;不难发现&#xff0c;对于杨氏矩阵老说&#xff0c;右上角和左下…

leetcode1020. 飞地的数量

https://leetcode.cn/classic/problems/number-of-enclaves/description/ 给你一个大小为 m x n 的二进制矩阵 grid &#xff0c;其中 0 表示一个海洋单元格、1 表示一个陆地单元格。 一次 移动 是指从一个陆地单元格走到另一个相邻&#xff08;上、下、左、右&#xff09;的…

哈希的应用->位图

ps&#xff1a;左移位并不是向左移动位&#xff0c;而是低数据位向高数据位挪动 位图&#xff08;主要接口&#xff0c;set(size_t)标识、reset(size_t)取消、test(size_t) 查看 给40亿个不重复的无符号整数&#xff0c;没排过序。给一个无符号整数&#xff0c;如何快速判断一…

做软件测试到底要不要学编程?

乔布斯曾经说过“每个人都应该学习编程&#xff0c;因为它会教你如何思考”&#xff0c;看&#xff0c;乔帮主都觉得所有人都应该学编程&#xff0c;那你说做测试的要不要学&#xff1f;当然要。 作为测试人员&#xff0c;除了上面这个原因&#xff0c;我觉得如果会编程&#x…

Android架构之MVC,MVP,MVVM解析

MVC架构 View&#xff1a;Acitivity(View)、Fragment(View)视图&#xff0c;在android里xml布局转成View后&#xff0c;加载到了Activity/Fragment里了。 Controller&#xff1a;Controller对应着Activity/Fragment&#xff0c;绑定UI&#xff0c;处理各种业务。 Model&#xf…

python接口自动化(三十)--html测试报告通过邮件发出去——中(详解)

简介 上一篇&#xff0c;我们虽然已经将生成的最新的测试报告发出去了&#xff0c;但是MIMEText 只能发送正文&#xff0c;无法带附件&#xff0c;因此我还需要继续改造我们的代码&#xff0c;实现可以发送带有附件的邮件。发送带附件的需要导入另外一个模块 MIMEMultipart。还…