【数组及指针经典笔试题解析】

news2025/1/14 20:40:48

1.数组和指针笔试题

题目1

int main()

{
     int a[5] = { 12345};
     int * ptr = (int * )(&a + 1);

     printf("%d,%d"*(a + 1)*(ptr - 1));
     return 0;

}

图文解析:

在这里插入图片描述

int * ptr = (int * )(&a + 1);
✍️.&a ——表示的是整个数组的地址,而在内存存储中,整个数组的地址其实是在首元素地址的前一个空间位置,所以&a所展示的位置如上图所示。
✍️.&a+1——在很多的数据类型中,+1表示的是加多少字节,字节数取决于类型数,而&a+1中的&a表示的是数组的地址,那么这就表示了加一个&a一样大小的字节数,然后抵达的地址。
✍️.而这个地址也如图整个数组地址一样,处在下一个数组之前的空间位置,或者处在这个数组空间之后的一个空间位置。
✍️.(int*)——&a+1表示的是数组的地址,而(int*)是进行强制类型转化,转化为int类型的指针地址

在这里插入图片描述

*(ptr - 1)
✍️.如图,结合上一步的分析, &a+1被强制类型转化为了int*类型的并赋予了同样类型的ptr
✍️.ptr的内部存放的是&a+1的地址,但是整个地址被转化为了int*类型
✍️.进行ptr-1后,这个-1的操作从数组数据类型变为了int类型的,因此-1减去的是四个字节,在int类型的数组中,四个字节表示一个元素,因此ptr-1便是如图中所示,移动到了数组的最后一个元素。
✍️.所以*(ptr-1)得到的结果是数组的最后一个元素 5

在这里插入图片描述

*(a + 1)
✍️.a——数组名,因为并不是在sizeof中,所以该处的a表示的是首元素的地址
✍️.a+1——在很多的数据类型中,+1表示的是加字节数,而加上的字节数取决于数据的类型,眼下的a表示的是首元素的地址,而首元素表示的是int类型,也因此+1表示的是加四个字节,也就从首元素地址变成了第二个元素的地址
✍️.*(a+1)——表示的就是第二个元素地址指向的元素,也就是第二个元素 2

结论:
1.&a+1 —— &a 表示的是数组的地址,+1加的是这个数组的总字节数大小后,抵达的位置。
2.a+1 ——a表示的是首元素的地址,+1加的是同这个元素一样的字节数大小后,抵达的位置。
3.加上的字节大小,看数组的数据类型或者元素的数据类型。

题目2

int main() 

{ 

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

      int *p; 

      p = a[0];  

      printf( "%d", p[0]); 

      return 0; 

}

图文解析:

在这里插入图片描述

int a[3][2] = { (0, 1), (2, 3), (4, 5) };
✍️.{ (0, 1), (2, 3), (4, 5) }内部并不是花括号括起来的,因此是逗号表达式!实际上{ }内只有三个元素。
✍️. int a[3][2] = { (0, 1), (2, 3), (4, 5) }; 实际上是int a[3][2] = { 1,3,5 }; 而其余的未满的元素全是0
✍️.所以,这个三行两列的矩阵应该是 第一行是 1 3 第二行是 5 0 第三行是0 0

p = a[0];
✍️.a[0] 表达的是二维数组第一行的数组名,既然是数组名又不在sizeof内,那代表的就是首元素的地址,那就是a[0][0]的地址,也就是元素 1

p[0]
✍️.p[0] 其实就是 *(p+0) 也就表示 元素 1
✍️.因为p = a[0] ; a[0]相当于数组名,而数组名[ ]的组合相当于是取数组中的某个元素的意思,所以p[0] 相当于a[0] [0] 其中的a[0]是数组名,所以取的是a[0]这个数组中下标位0的元素,a[0]表示的是第一行,所以取的是第一行中下标为0的元素。

题目3

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; 

}

图文解析:

在这里插入图片描述

int(*p)[4];
✍️.定义了指针变量p是一个数组指针,且该数组指针指向的数组内具有四个元素。
✍️.当进行p+1的时候,加上的就是四个元素的字节大小之和。

p = a;
✍️.a表示的是数组名,二维数组的数组名表示的是二维数组的第一行的地址,由于地址的特性,是处在数组元素之前的内存空间内。
✍️.所以如上图所示

在这里插入图片描述

&p[4][2] - &a[4][2];
✍️.因为p是一个int类型的指针数组,指针数组的跨度是4个元素,而p[4][2] 相当于一个二维数组,取的是第四行下标为2的元素。
✍️.&a[4][2]取的就是a数组中第四行下标为2的元素的地址
✍️. &p[4][2] 表示的就是p+4这一个跨度中,下标为2的元素地址和&a[4][2]相减,得到的是-4。

题目4

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;

 }

图文解析:

在这里插入图片描述

int *ptr1 = (int *)(&aa + 1);
✍️.&aa表示整个数组的地址,&aa+1表示越过了一个数组大小的地址位置,整个数组的地址在首元素地址之前的内存空间中,因此如上图所示。
✍️.(int*)是强制类型转化,将其转化为int类型的指针。

int *ptr2 = (int *)(*(aa + 1));
✍️.aa相当于首元素地址,在二维数组中首元素地址就是第一行的地址,而aa+1表示的就是第二行地址
✍️.且aa+1 又可以转化为aa[1]表示数组名,表示的是第二行的数组名,那么可以表示第二行第一个元素的地址而就表示第二行第一个元素,此处的int强制类型转化是没有用的。

在这里插入图片描述

*(ptr1 - 1), *(ptr2 - 1)
*(ptr1 - 1)
✍️.*(ptr1-1) ptr因为是int类型的指针,且被传输了&aa+1的地址,那么ptr-1根据数据类型-1就是减去四个字节,所以根据上图所示,我们得知ptr-1就是指向整个数组的最后一个元素。
✍️.*(ptr-1)就是最后一个元素 10

*(ptr2 - 1)
✍️,ptr2-1就是第二行第一个元素减一,就是第一行最后一个元素,所以表示的就是元素5

结论:
在二维数组中,数组名+1 = 数组名[1] 即表示第二行的地址又表示了第二行第一个元素的地址。

题目5

int main()

{

      char *a[] = {"work","at","alibaba"};

      char**pa = a;

      pa++; 

      printf("%s\n", *pa);

      return 0; 

}

图文解析:

在这里插入图片描述

char *a[] = {"work","at","alibaba"};
✍️.字符指针类型的数组,字符串传递地址时,是传递的首字符的地址。

char**pa = a;
✍️.a是数组名,数组名就是首元素的地址,所以pa指向的就是首元素的地址,如上图所示。

在这里插入图片描述

pa++;
✍️.pa++指向的是第二个元素的地址。

printf("%s\n", *pa);
✍️.经历了pa++后,pa指向的是字符指针数组的第二个元素,而在第二个元素中寄存的是字符串at的首字符地址,所以*pa也就是表示的是at的首字符a,但由于printf打印的是%s格式,%s是字符串格式,所以打印的是字符串at

在这里插入图片描述

题目6

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; 

}

图文解析:

在这里插入图片描述

char *c[] = {"ENTER","NEW","POINT","FIRST"};
✍️.创建了一个字符指针数组,指针数组的内部存储的是各个字符串的首个字符的地址。

char**cp[] = {c+3,c+2,c+1,c};
✍️.cp是一个二级指针数组,数组的内部存储的是字符指针数组c的某些地址。
✍️.c+3——其中c是指针数组c的数组名,表示的是数组中首元素的地址,也便是c[0]的地址,而c+3表示的是往后加上三个元素的地址后抵达的位置,可以当作c[3]的地址。
✍️.c+2——同理,表示c[2]代表的元素地址
✍️.c+1——表示的是c[1]代表的元素地址
✍️.c——表示的是首元素地址

在这里插入图片描述

char***cpp = cp;
✍️.cpp是三级指针,cpp内存储的是cp的首元素地址。

printf("%s\n", **++cpp);
✍️.++使得cpp发生改变,原先的cpp内存储的是cp的首元素地址,在++后因为是指针数组,++表示的是向后加一个元素大小的地址,也就是第二个元素的地址。
✍️.因此在++后,这里的cpp存储的是cp1的第二个元素,c+2
✍️.于是乎就变成了**(c+2),先解决第一个*c+2cp内,cp也是一个指针,所以c+2指向的是c中的第三个元素,POINT的首字符P的地址
✍️.于是乎就变成了*P的首字符地址)
✍️.最后在解除最后一个*,且因为打印的格式是%s,所以打印除的结果是POINT

在这里插入图片描述

printf("%s\n", *--*++cpp+3);
✍️.按照优先级,先进行++cpp运算,因为++是有累计性的,所以cpp此刻存储的是cp中第二个元素的地址,如上图所示,因此在进行++后,cpp指向(存储)的地址变成了cp的第三个元素地址,也就是c+1的地址,所以变成了*--*(&cp[2])+3
✍️.(&cp[2])表示的是cp中第三个元素的地址,最后通过*得到了内部存储的元素c+1,所以现在的结果是*--(c+1)+3
✍️.*--(c+1)+3,在进行-- ,将c+1进行-- 得到的结果是c,于是变成了*(c)+3
✍️.c指向的内容是字符串ENTER的首字符E的地址,所以在*后得到的是 'E'+3
✍️.'E'+3E是字符类型,+3,相当于是加了三个字符类型的字节数大小,于是结果变成了ENTER中的第二个E
✍️.最后打印的格式是%s,所以打印的结果是ER

在这里插入图片描述

printf("%s\n", *cpp[-2]+3);
✍️.由于++是有累积性的,所以cpp中存储的地址是cp的第三个元素的地址
✍️.cpp[-2],表示的是一个元素,根据 *(数组名+ 0) =数组名[0] ,数组名[0]也表示一个元素 ,而数组名又表示首元素地址,我们得到结论,*(数组名+0)=数组名[0] =*( 首元素地址 +0)
✍️.而cpp是存储地址的指针,因此cpp[-2]我们可以得到,cpp现在所指向的地址-2之后得到的元素。
✍️.cpp当前的地址是经过了上一次的++累加后,变成了如上图所示,指向的是cp的第三个元素,所以在-2后得到的结果是指向了cp的第一个元素,而第一个元素的内容是c+3
✍️.所以cpp[-2]= c+3
✍️.*cpp[-2]+3 ————> *(c+3)+3
✍️.c是一个数组名,表示的是数组首元素地址,而c+3根据数组名+n = &数组名[n]的原理,我们得到了c+3是表示首元素地址+3个元素的字节大小后后抵达的地址
✍️.在c中下标为3的元素是字符串FIRS的首字符地址,所以c+3表示的就是字符F的地址
✍️.随后得到 *(c+3)+3————>'F'+3
✍️.因为F是字符,且+3相当于是加上三个相同类型的字节数,又因为打印的各式是%s,所以得到的结果是ST

在这里插入图片描述

printf("%s\n", cpp[-1][-1]+1);
✍️.cpp内存储的依旧是cp中第三个元素的地址
✍️.cpp[-1][-1]并不是二维数组所表达的意思,根据数组名[n] = *(数组名+n)的原理,进行计算,可以先将cpp[-1]当作数组名,那么我们可以转化为*(cpp[-1] +(-1))
✍️.而后,又将cpp当作数组名进行运算,那么我们可以转化为*(*(cpp+(-1))+(-1))——>*(*(cpp-1)-1)
✍️.而cpp中存储的是cp中第三个元素的地址,在进行-1后cpp中存储的地址发生了改变,变成了cp中第二个元素的地址,也就是c+2整个元素所在的地址,而通过第一个*后得到的结果就是c+2
✍️.所以式子变成了*(c+2-1)
✍️.内部运算,得到的结果是*(c+1)
✍️.最后整个式子是*(c+1)+1,而c是数组名,表示的是数组c的首元素地址,于是c+1表示的就是第二个元素的地址,在通过*得到的就是数组c的第二个元素
✍️.数组c的第二个元素是字符串NEW的首字符地址,所以最后的+1就是首字符地址加一,通过同类型原理,得到的就是第二个字符的地址
✍️.又因为打印的方式是%s所以最后的结果是EW

结论:
✍️.*(数组名+ 0) =数组名[0],这里的数组名表示的是首元素地址
✍️.数组名[n]表示的是在这个数组中,下标为n的元素的地址,也可以说为&数组名[n]
✍️.数组名[n][n]这个数组并不是二维数组时,可以得到数组名[n][n]= *(*(数组名+n)+n)

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

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

相关文章

【数据结构】堆的应用-----TopK问题

目录 一、前言 二、Top-k问题 💦解法一:暴力排序 💦解法二:建立N个数的堆 💦解法三:建立K个数的堆(最优解) 三、完整代码和视图 四、共勉 一、前言 在之前的文章中&#xff…

SpringCloudGateway实现数字签名与URL动态加密

文章目录 对称加密非对称加密什么是数字签名HTTPS与CA⭐Gateway网关的过滤器链如何对自己的路径传输设定一个数字签名?前端获取RSA公钥发送加密后对称密钥后端接收当前会话对称密钥并保存前端发送AES加密请求验证请求 如何实现URL的动态加密? 再网络传递…

HTML开篇之安装VSvode(用记事本编辑HTML)

文章目录 前端开篇开篇知识点讲解1.HTML 结构1.1认识 HTML 标签1.2HTML 文件基本结构1.3标签层次结构1.4快速生成代码框架1.5用记事本写HTML1.6前端开发工具1.7下载vscode 及使用教学 大家好,我是晓星航。今天为大家带来的是 HTML 相关的讲解!&#x1f6…

凉鞋的 Unity 笔记 105. 第一个通识:编辑-测试 循环

105. 第一个通识:编辑-测试 循环 在这一篇,我们简单聊聊此教程中所涉及的一个非常重要的概念:循环。 我们在做任何事情都离不开某种循环,比如每天的 24 小时循环,一日三餐循环,清醒-睡觉循环。 在学习一…

在线OJ项目核心思路

文章目录 在线OJ项目核心思路1. 项目介绍2.预备知识理解多进程编程为啥采用多进程而不使用多线程?标准输入&标准输出&标准错误 3.项目实现题目API实现相关实体类定义新增/修改题目获取题目列表 编译运行编译运行流程 4.统一功能处理 在线OJ项目核心思路 1. 项目介绍 …

【每日一题】买卖股票的最佳时机 III

文章目录 Tag题目来源题目解读解题思路方法一:动态规划 写在最后 Tag 【动态规划】【数组】【2023-10-03】 题目来源 123. 买卖股票的最佳时机 III 题目解读 有一个表示股票价格的数组,你需要计算出在最多可以完成两笔交易的前提下可获得的最大收益&a…

什么样的枕头可以让睡眠更舒适——四个月的反复试验结果

如何提高睡眠质量,我们先从睡眠中的呼吸质量谈起,这里面有大量的数据和记录,我后续会整理我这七八年来积累的所有睡眠质量数据进行分析汇总和处理。 几个月前我在看我的华为手表监控的睡眠数据时看到了关于睡眠中呼吸质量的数据,最…

1.6 计算机网络的性能

思维导图: 1.6.1 计算机网络的性能指标 前言: 我的理解: 这段前言主要介绍了关于计算机网络性能的两个方面的讨论。首先,计算机网络的性能可以通过一些重要的性能指标来衡量。但除了这些指标之外,还有一些非性能特征…

【强化算法专题一】双指针算法

【强化算法专题一】双指针算法 1.双指针算法--移动零2.双指针算法--复写零3.双指针算法--快乐数4.双指针算法--盛水最多的容器5.双指针算法--有效三角形的个数6.双指针算法--和为s的两个数7.双指针算法--三数之和8.双指针算法--四数之和 1.双指针算法–移动零 算法原理解析----…

BIT-6自定义类型和动态内存管理(11000字详解)

一:自定义类型 1.1:结构体 在生活中,基本数据类型可以描述绝大多数的物体,比如说名字,身高,体重,但是还有一部分物体还不足够被描述,比如说我们该如何完整的描述一本书呢&#xff…

VSCode安装图文详解教程

版权声明 本文原创作者:谷哥的小弟作者博客地址:http://blog.csdn.net/lfdfhl 教程说明 本教程旨在详细介绍VSCode的安装过程及其注意事项。 下载VSCode 请在官方网站 https://code.visualstudio.com/ 下载https://code.visualstudio.com/至本地&…

Android学习之路(18) 数据存储与访问

文件存储读写 1.Android文件的操作模式 学过Java的同学都知道,我们新建文件,然后就可以写入数据了,但是Android却不一样,因为Android是 基于Linux的,我们在读写文件的时候,还需加上文件的操作模式&#x…

设计模式之适配器模式:接口对接丝般顺滑(图代码解析面面俱到)

目录 概要概念组成类图工作原理应用场景优点 类型类适配器模式对象适配器模式两者区别示例代码 实现(对象适配器详解)业务背景代码 常见问题为什么有适配器模式适配器模式告诉我们什么适配器模式体现了哪些设计原则关联方式实现了逻辑继承适配器模式在Sp…

春招秋招,在线测评应用得越来越普及

这年代提到测评,很多人都比较熟悉,它有一种根据所选的问题给予合适答案方面的作用。因为不同的测评带来的影响不一样,所以很多人都会关注在线测评的内容有哪些。在校园招聘上面,在线测评也频繁出现了,这让很多人好奇它…

VD6283TX环境光传感器驱动开发(2)----获取光强和色温

VD6283TX环境光传感器驱动开发----1.获取光强和色温 概述视频教学样品申请源码下载参考源码设置增益基准配置设置ALS曝光时间通道使能启用ALS操作中断查询及清除获取ALS数据计算光强及色温结果演示 概述 为了更好地利用VD6283TX传感器的特点和功能,本章专门用于捕获…

用通俗易懂的方式讲解大模型分布式训练并行技术:张量并行

近年来,随着Transformer、MOE架构的提出,使得深度学习模型轻松突破上万亿规模参数,传统的单机单卡模式已经无法满足超大模型进行训练的要求。因此,我们需要基于单机多卡、甚至是多机多卡进行分布式大模型的训练。 而利用AI集群&a…

最近脑机接口突破性成果这么多,它到底走到哪一步了?

美国心脏协会(AHA)首席临床科学官、哥伦比亚大学神经病学和流行病学终身教授Mitchell Elkind在接受NeuroNews采访时概述了脑机接口(BCI)技术的巨大潜力:“恢复患者活动能力的可能性可能会带来巨大的好处。”“对于那些功能受限的人来说,即使是微小的进步也能改变他们…

【数仓精品理论分析】能不能学大数据?

【数仓精品理论分析】能不能学大数据? 还能不能学大数据datapulse官网: 自身情况数据行业发展情况 还能不能学大数据 首先看到这个话题的时候,我是这样想的,能不能学大数据需要参考本人的自身情况【学历、年龄、决心、有没有矿或者…

高層建築設計和建造:從避難層到設備間和防風防火防水的設計理念,酒店住宅辦公樓都有什麽房間(精簡)

樓層概覽 標準層居住、辦公、商業等功能的樓層。結構和裝修與其他樓層相同,可供人正常居住、工作和活動避難層專門用於人員避難的樓層,通常會相隔數十個標準層,樓梯通常和標準層是錯開的(非公用),具有更多的通風口。牆體和樓板具…

黑豹程序员-架构师学习路线图-百科:CSS-网页三剑客

文章目录 1、为什么需要CSS2、发展历史3、什么是CSS4、什么是SASS、SCSS 1、为什么需要CSS 作为网页三剑客的第二,CSS为何需要它,非常简单HTML只能完成页面的展现,但其做出来的页面奇丑无比。 随着网络的普及,人们的要求更高&…