【C语言进阶篇】关于指针的八个经典笔试题(图文详解)
文章目录
- 📋 前言
- 💬 指针笔试题
- 💭 笔试题 1:
- ✅ 代码解析
- ⁉️ 检验结果:
- 💭 笔试题 2:
- ✅ 代码解析
- ⁉️ 检验结果:
- 💭 笔试题 3:
- ✅ 代码解析
- ⁉️ 检验结果
- 💭 笔试题 4:
- ✅ 代码解析
- ⁉️ 检验结果
- 💭 笔试题 5:
- ✅ 代码解析
- ⁉️ 检验结果
- 💭 笔试题 6:
- ✅ 代码解析
- ⁉️ 检验结果
- 💭 笔试题 7:
- ✅ 代码解析
- ⁉️ 检验结果
- 💭 笔试题 8:
- ✅ 代码解析
- ⁉️ 检验结果
- 📝全篇总结
📋 前言
🌈hello! 各位宝子们大家好啊,指针系列的讲解我们就全部讲解完毕了,那么接下来就是来检验成果的时候了?
⛳️今天来做一做指针的面试题到底是个什么难度!你真的学会了指针了嘛?这篇文章让你融汇贯通
📚本期文章收录在《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;
}
//程序的结果是什么?
✅ 代码解析
printf( “%d,%d”, *(a + 1), *(ptr - 1));
其实没什么难的,我相信各位铁子们已经想出答案了!关于数组的笔试题我们做了那么多,&数组名就是拿出整个数组的数组名而+1就是跳过整个数组+1;
-
所以 *(ptr-1)就是回到了数组的最后一个元素的位置
-
-
然后进行解引用 结果就是:5
-
*(a + 1) a 是首元素的地址,所以+1 就是指向第二个元素的地址
-
-
然后进行解引用 结果就是:2
⁉️ 检验结果:
📑图片展示:
💭 笔试题 2:
//由于还没学习结构体,这里告知结构体的大小是20个字节
struct Test
{int Num;char *pcName;short sDate;char cha[2];short sBa[4];
}*p;
//假设p 的值为0x100000。 如下表表达式的值分别为多少?
//已知,结构体Test类型的变量大小是20个字节
int main()
{printf("%p\n", p + 0x1);printf("%p\n", (unsigned long)p + 0x1);printf("%p\n", (unsigned int*)p + 0x1);return 0;
}
🔥 注:本代码是在32位环境下测试的。
✅ 代码解析
printf(“%p\n”, p + 0x1);
这里就非常有意思了指针加一我们都知道是跳过指针类型的大小,整形指针跳过4个字节,字符指针跳过1个指针。而我们这里结构体的大小是20个字节,所以+1跳过的就是20个字节!
- 但是要注意这里是以16进制输出的所以
20
的16进制就是14
- printf(“%p\n”, p + 0x1);
- 的结果为 0x100014。
printf(“%p\n”, (unsigned long)p + 0x1);
而这里则强制转换成了整形,而强转成整形的话。那么 p 就是一个整数了。而整数+1就是 +1 没有什么变化!
- printf(“%p\n”, (unsigned long)p + 0x1);
- 的结果为 0x100001。
printf(“%p\n”, (unsigned int*)p + 0x1);
这里指针 p 被强制转换为了无符号整形,而无符号整形+1。就是跳过4个字节。
- printf(“%p\n”, (unsigned int*)p + 0x1);
- 的结果为 0x100004。
🌴 总结:
- 这里运用了指针的运算和进制位的转换,这要这些知识掌握了。截图就非常easy了!
- 注:指针运算的博客在这里《指针的运算详解》
⁉️ 检验结果:
💭 笔试题 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;
}
✅ 代码解析
int *ptr1 = (int *)(&a + 1);
我们先来看一下,&a先把整个数组的地址拿出来然后进行+1然后强制转换为 int 类型的指针传给我们 ptr1。*
- 那么 *ptr1,不就指向与数组相邻的那个元素了吗!
- ptr1[-1] 就右回到了,数组的最后一个元素
int *ptr2 = (int *)((int)a + 1);
🔥 注:这里需要用到 大小端存储的概念!不会的也去看看 这里只简单讲解哦!
这里就非常有意思了,a是数组首元素的地址。这里却把它强制转换为了整数,然后+1是在括号里面所以a+1,在转换为int* 类型的地址就只跳过了一个字节!
-
然后再进行+1 跳过4个字节,进行解引用访问4个字节
-
所以int *ptr2 = (int *)((int)a + 1);
-
🔥 *ptr2 的结果是 0x02000000
这里给大家解释一下大小端存储,就地址存低位,高地址存高位。所以拿出来的时候低地址就是低位,高地址当高位还原的。
- 这里02是在高地址的所以拿出来的时候直接就放在高位了
⁉️ 检验结果
💭 笔试题 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]);return 0;
}
✅ 代码解析
int a[3][2] = { (0, 1), (2, 3), (4, 5) };
这里陷阱就比较多了,一定要注意二维数组的时候是用大括号进行赋值的。而这里使用括号说明他是逗号表达式。
- 所以a[3][2] = {1,3,5};
- 而 a[0] = *(a+0) = *p 等于二维数组第一排首元素的地址
- int a[3][2] = { (0, 1), (2, 3), (4, 5) };
- 结果为 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;
}
✅ 代码解析
这个题也是一个陷阱,我们首先要搞懂,数组的地址变化是由数组下标由低到高变化的而且数组还是一块连续的储存空间。
- int(*p)[4]; p = a;这里要搞懂赋值给p的是什么,由于
a
是 int (*)[5] 指针p
是 int (*)[4] 所以会发生隐式转换。到int (*)[4]
这里我们就可以看到p[4][2]a[4][2]之间相差了,4个整形的长度。
- 我们知道指针运算里面 指针 - 指针 的=得到的是指针之间元素的个数!
- printf( “%p,%d\n”, &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]);
- 所以得到的是 -4 这个数值!
但是如果以地址打印的话得到的就是,-4 在内存中存储的数字。而 -4 在内存中是以补码的形式存储的。
- 所以以 %p 打印结果就是 FFFFFFFC。
- 以 %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 取出的是整个二维数组的地址。+1 就是跳过整个数组指向数组后一个元素。
- **int *ptr1 = (int *)(&aa + 1); **
- printf( “%d”, *(ptr1 - 1), );
- 所以在进行 -1 的时候就访问到了数组的最后一个元素 10。
而 *ptr2 = (int *)(*(aa + 1));这里 aa 代表的就不是首元素的地址了,而是一维数组 aa[0] 整个一维数组的地址,所以+1 就跳到了 aa[1].
- *ptr2 = (int )((aa + 1));
- printf( “%d”, *(ptr2 - 1));
- 所以在进行 -1 就又回到了aa[0] 的最后一个元素 5。
⁉️ 检验结果
💭 笔试题 7:
#include <stdio.h>
int main()
{char *a[] = {"work","at","alibaba"};char**pa = a;pa++;printf("%s\n", *pa);return 0;
}
✅ 代码解析
这里要注意也是一个陷阱, char *a[] = {“work”,“at”,“alibaba”}; a[ ]
里面可以当成存放的是一维数组字符串首元素的地址。所以当我们把 字符指针 数组 *a[]
存放到 二级指针 pa 里面的时候他们的内存布局就应该是这样的!
- pa++ 就指向 a[1] 而对一个地址进行解引用,得到的是a[1] 这个字符指针指向的字符串
- 所以: printf(“%s\n”, *pa);
- 的结果是 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;
}
✅ 代码解析
做这种题首先把图画出来就简单多了
printf(“%s\n”, **++cpp);
**++cpp指向的就是 cp[1] , 向前了一小步。这时看这我们上面画的图就简单多了!而这时又进行了俩次解引用不就找到 c[2]嘛!
- printf(“%s\n”, **++cpp);
- 的结果为 POINT。
printf(“%s\n”, *--*++cpp+3);
这个首先要把运算符的逻辑关系搞清楚,做这个题就简单多了 ++ -- 的运算符关系是比 + 号运算优先级要高的。
- 但是这里要注意前面的 ++ 是会影响指针的指向的 。
- 那么先++在解引用就找到了这里 *++
- 在 -- 在解引用就找到了这里 *-- , c这个首元素地址
- 但是这里还进行了 +3 那么就要跳过3个 char 字节在打印
-
printf(“%s\n”, *--*++cpp+3);
-
所以结果为 ER
printf(“%s\n”, *cpp[-2]+3);
这里我们和上面一样, *cpp[-2]+3 = *(cpp-2)+3 , 我们把它简化一下就简单多了!
- 这里依旧要注意前面是改变了 cpp的指向 。
- 所以
cpp-2
然后再进行解引用指向的就是这里 - 然后再进行 +3 跳过3个字节进行打印
- printf(“%s\n”, *cpp[-2]+3);
- 结果为 ST
printf(“%s\n”, cpp[-1][-1]+1);
诶这里大家千万不要进入误区了,使用下表引用是不会改变 指针的指向的,所以我们cpp 指向的还是 cp[2]。
-
cpp[-1][-1]+1 = ((cpp-1)-1)+1
-
先 -1 然后再进行解引用,就找到了这里
- 在 -1 然后再进行解引用,就找到了这里
- 在 -1 然后再进行解引用,就找到了这里
-
然后再进行 +1 打印出来就是从这个位置开始的!
-
printf(“%s\n”, cpp[-1][-1]+1);
-
**结果为 EW **
⁉️ 检验结果
📝全篇总结
✅ 归纳:
好了以上就是关于经典的八个经典笔试题的详细解析,包含了个个方面的知识不知道大家做的怎么样呢!
指针 - 指针的运算
操作符的优先级
++ 对指针的影响
[] *() 的理解
指针的运算
☁️ 这些就是全部指针 and 数组的全部知识的总结了,不知道大家掌握的怎么样呢?
看到这里了还不给博主扣个:
⛳️ 点赞
☀️收藏
⭐️ 关注
!
💛 💙 💜 ❤️ 💚💓 💗 💕 💞 💘 💖
拜托拜托这个真的很重要!
你们的点赞就是博主更新最大的动力!
有问题可以评论或者私信呢秒回哦。
相关文章:

【C语言进阶篇】关于指针的八个经典笔试题(图文详解)
🎬 鸽芷咕:个人主页 🔥 个人专栏:《C语言初阶篇》 《C语言进阶篇》 ⛺️生活的理想,就是为了理想的生活! 文章目录 📋 前言💬 指针笔试题💭 笔试题 1:✅ 代码解析⁉️ 检验结果&…...
用Rust实现23种设计模式之 策略模式
关注我,学习Rust不迷路!! 优点 灵活性:策略模式允许你在运行时动态地选择不同的算法或行为,而无需修改已有的代码。可扩展性:通过添加新的策略类,你可以轻松地扩展策略模式的功能。可维护性&a…...

面试题:说说JS的this指向问题?
1、this永远指向一个对象; 2、this的指向完全取决于函数调用的位置; 可以借鉴这篇文章,说的很详细(点击) 总结: 1、 以方法的形式调用时, this 是调用方法的对象; 2、绑定事件函…...
ansible——roles 角色
一、概述 1.roles角色简介 roles用于层次性、结构化地组织playbook。roles能够根据层次型结构自动装载变量文件、tasks以及handlers等。要使用roles只需要在playbook中使用include指令引入即可。 简单来讲,roles就是通过分别将变量、文件、任务、模板及处理器放置…...

GitHub上删除项目后,IDEA分享项目到GitHub提示Remote is already on GitHub
文章目录 一、错误信息二、解决方法1.删除GitHub上的项目2.找到项目里的.git隐藏文件3.找到config文件4.打开config文件,删除[remote "git-test"]及下面两行内容5.继续使用IDEA分享项目到GitHub即可 一、错误信息 二、解决方法 1.删除GitHub上的项目 2.…...

【机器学习 | 决策树】利用数据的潜力:用决策树解锁洞察力
🤵♂️ 个人主页: AI_magician 📡主页地址: 作者简介:CSDN内容合伙人,全栈领域优质创作者。 👨💻景愿:旨在于能和更多的热爱计算机的伙伴一起成长!!&…...

postgis mvt矢量切片 django drf mapboxgl
postgis mvt矢量切片 django drf mapboxgl 目录 0.前提 1.sql代码 2.django drf后端服务代码 3.具体的应用(整体代码) 4.参考 0.前提 [1] 静态的矢量切片可以采用 tippecanoe 生成,nginx代理,这种数据是不更新的;…...
C语言编程工具软件推荐!
1、VS(Visual Studio) [VS是目前最受欢迎的适用于Windows平台应用程序的综合开发环境,由于大多数同学使用的都是Windows操作系统,因此VS非常适合大家。在日常课堂和考试中,我们使用的VS2010支持多种不同的编程语言,VS2010最初支持…...

单体架构和微服务架构的区别
文章目录 一、单体架构的定义1. 单体架构的优点:2. 单体架构的缺点: 二、微服务架构的定义1. 微服务架构的优点:2. 微服务架构的缺点: 三、单体架构VS微服务架构1. 区别:1.1 架构规模:1.2 依赖关系…...
python--local对象、flask上下文源码分析
一、local对象 背景: 多线成并发操作一个变量,会导致数据错乱,可以使用互斥锁加锁处理数据不安全的情况 (临界区) 解决: 使用local对象处理,多个线程操作的变量是local对象,就不会…...

类文件一些内容
1、类加载 将类的字节码加载到JVM中,并转换为可以被JVM运行的数据结构的过程 类文件结构...
28 Java练习——实现两个集合的交集和并集
求并集的思路:假设传入的是一个ArrayList对象,求并集的时候直接调用其中一个List集合的addAll方法将另一个集合合并过来,而List的特性是有序,重复的。因此,使用Set接口的无序不可重复的特性,把Collection对…...
ES6学习-Promise
Promise 简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。 语法上: Promise 是一个对象,从它可以获取异步操作的消息。 特点 对象的状态不受外界影响。Promise 对象戴白哦一个异步操…...

《Web安全基础》03. SQL 注入
web 1:简要 SQL 注入2:MySQL 注入2.1:信息获取2.2:跨库攻击2.3:文件读写2.4:常见防护 3:注入方法3.1:类型方法明确3.2:盲注3.3:编码3.4:二次注入3…...

算法与数据结构(二十一)二叉树(纲领篇)
备注:本文旨在通过 labuladong 的二叉树(纲领篇)理解框架思维,用于个人笔记及交流学习,版权归原作者 labuladong 所有; 我刷了这么多年题,浓缩出二叉树算法的一个总纲放在这里,也许…...

visio,word添加缺少字体,仿宋_GB2312、楷体_GB2312、方正小标宋简体等字体下载
一. 内容简介 visio,word添加缺少字体,仿宋_GB2312、楷体_GB2312、方正小标宋简体等字体下载 二. 软件环境 2.1 visio 三.主要流程 3.1 下载字体 http://www.downza.cn/ 微软官方给的链接好多字体没有,其他好多字体网站,就是给你看个样式ÿ…...
Java爬虫
什么是爬虫? 通过请求,从而去获取互联网上的各种数据与资源,如文字,图片,视频。 本质上原理都一样,都是通过api请求,然后服务器就会发给你信息,然后你再根据这些信息去提取你想要的…...

海外应用商店优化实用指南之关键词
和SEO一样,关键词是ASO中的一个重要因素。就像应用程序标题一样,在Apple App Store和Google Play中处理应用程序关键字的方式也有所不同。 关键词研究。 对于Apple,我们的所有关键词只能获得100个字符,Google Play没有特定的关键…...

element+vue 之动态form
1.页面部分 <div v-for"(item,index) in formList" :key"index"><el-col :span"6" v-if"item.inputType0"><el-form-item :label"item.conditionName" :prop"item.conditionCode":rules"{req…...

winform学习(3)-----Windows窗体应用和Windows窗体应用(.Net Framework)有啥区别?
1.模板选择 在学习winform的时候总是会对这两个应用不知道选择哪个?而且在学习的时候也没有具体的说明 首先说一下我是在添加控件的时候出现了以下问题 对于使用了Windows窗体应用这个模板的文件在工具箱中死活不见控件。 在转换使用了Windows窗体应用(.NET Fram…...

龙虎榜——20250610
上证指数放量收阴线,个股多数下跌,盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型,指数短线有调整的需求,大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的:御银股份、雄帝科技 驱动…...
Java 语言特性(面试系列1)
一、面向对象编程 1. 封装(Encapsulation) 定义:将数据(属性)和操作数据的方法绑定在一起,通过访问控制符(private、protected、public)隐藏内部实现细节。示例: public …...
基于服务器使用 apt 安装、配置 Nginx
🧾 一、查看可安装的 Nginx 版本 首先,你可以运行以下命令查看可用版本: apt-cache madison nginx-core输出示例: nginx-core | 1.18.0-6ubuntu14.6 | http://archive.ubuntu.com/ubuntu focal-updates/main amd64 Packages ng…...

iPhone密码忘记了办?iPhoneUnlocker,iPhone解锁工具Aiseesoft iPhone Unlocker 高级注册版分享
平时用 iPhone 的时候,难免会碰到解锁的麻烦事。比如密码忘了、人脸识别 / 指纹识别突然不灵,或者买了二手 iPhone 却被原来的 iCloud 账号锁住,这时候就需要靠谱的解锁工具来帮忙了。Aiseesoft iPhone Unlocker 就是专门解决这些问题的软件&…...

【机器视觉】单目测距——运动结构恢复
ps:图是随便找的,为了凑个封面 前言 在前面对光流法进行进一步改进,希望将2D光流推广至3D场景流时,发现2D转3D过程中存在尺度歧义问题,需要补全摄像头拍摄图像中缺失的深度信息,否则解空间不收敛…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院挂号小程序
一、开发准备 环境搭建: 安装DevEco Studio 3.0或更高版本配置HarmonyOS SDK申请开发者账号 项目创建: File > New > Create Project > Application (选择"Empty Ability") 二、核心功能实现 1. 医院科室展示 /…...

OPENCV形态学基础之二腐蚀
一.腐蚀的原理 (图1) 数学表达式:dst(x,y) erode(src(x,y)) min(x,y)src(xx,yy) 腐蚀也是图像形态学的基本功能之一,腐蚀跟膨胀属于反向操作,膨胀是把图像图像变大,而腐蚀就是把图像变小。腐蚀后的图像变小变暗淡。 腐蚀…...
为什么要创建 Vue 实例
核心原因:Vue 需要一个「控制中心」来驱动整个应用 你可以把 Vue 实例想象成你应用的**「大脑」或「引擎」。它负责协调模板、数据、逻辑和行为,将它们变成一个活的、可交互的应用**。没有这个实例,你的代码只是一堆静态的 HTML、JavaScript 变量和函数,无法「活」起来。 …...
【SpringBoot自动化部署】
SpringBoot自动化部署方法 使用Jenkins进行持续集成与部署 Jenkins是最常用的自动化部署工具之一,能够实现代码拉取、构建、测试和部署的全流程自动化。 配置Jenkins任务时,需要添加Git仓库地址和凭证,设置构建触发器(如GitHub…...

Canal环境搭建并实现和ES数据同步
作者:田超凡 日期:2025年6月7日 Canal安装,启动端口11111、8082: 安装canal-deployer服务端: https://github.com/alibaba/canal/releases/1.1.7/canal.deployer-1.1.7.tar.gz cd /opt/homebrew/etc mkdir canal…...