进阶C语言:指针笔试题

news/2024/5/17 5:06:43/文章来源:https://blog.csdn.net/Yikefore/article/details/129753994

在学习完进阶C指针之后,可以来做一些笔试题来进行提升、巩固,小编在这里给大家分享几道比较有意思的笔试题

目录

 

一、笔试题1:

二、笔试题2

三、笔试题3:

 四、笔试题4:

五、笔试题5:

​编辑

六、笔试题6:

七、笔试题7:

八、笔试题8:


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

解析:

这是一段比较简单的代码,关于上面的代码,可以分析一下,a是一个整形数组,里面有五个元素,ptr是一个整形指针,&a+1表示的是跳过一个a数组,类型是一个数组指针的类型,所以要强制转换为整形指针才可以存放在ptr中,所以ptr指向的就是a数组后面的那个地址。

 

 *(a+1)中的a表示数组首元素的地址,+1表示跳过一个整形,指向数组的第二个元素的地址,然后解引用,得到数组的第二个元素,所以*(a+1)的结果是2

*(ptr-1)中的ptr是一个整形指针,指向的是a数组后面的地址,-1表示向前移动1个整形,所以指向了数组的最后一个元素的地址,然后解引用,得到的就是数组的最后一个元素,所以*(ptr-1)的结果是5

二、笔试题2

假设p 的值为0x100000。 如下表表达式的值分别为多少?
已知,结构体Test类型的变量大小是20个字节

#include <stdio.h>struct Test
{int Num;char* pcName;short sDate;char cha[2];short sBa[4];
}*p;int main()
{printf("%p\n", p + 0x1);printf("%p\n", (unsigned long)p + 0x1);printf("%p\n", (unsigned int*)p + 0x1);return 0;
}

解析:

Test是一个结构体,p是一个结构体指针,已知结构体的大小是20,所以结构体指针在加减整数的时候移动的单位就是20,p的初始值为0x100000,这是一个16进制的数字,以0x开头的为16进制数字

p+0x1中的p指向的是结构体,+1表示跳过一个结构体,由已知结构体的大小是20,所以p由起始的0x100000要加上20,20的16进制就是0x14,所以p+0x1的结果是0x100014

(unsigned long)p+0x1表示先把p强制类型转化为无符号长整形然后再加1,既然是整形那就相当于整数,整数加1就只是单纯的加1,所以(unsigned long)p+0x1的结果是0x100001

  (unsigned int*)    p + 0x1表示先把p强制类型转化为无符号的整形指针,既然是整形指针,加减整数表示跳过整形个单位,所以(unsigned int*)p + 0x1的结果是0x100004

三、笔试题3:

//代码运行结果是什么?
#include <stdio.h>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;
}

解析:

a是一个整形数组,&a+1表示取出整个数组的地址然后地址跳过一个数组,这时它的类型是一个指针数组的类型,强制类型转化为int*用ptr1来接受,ptr[-1]可以写成*(ptr-1),ptr是一个整形指针,-1表示移动一个整形,所以就指向了4这个元素的地址,然后解引用就得到了4

所以ptr[-1]的结果是4

a表示数组首元素的地址,然后将其强制类型转化为int类型,然后+1就表示单纯的加1,如果这时a的地址是0x0012ff40,那么+1之后的结果就变成了0x0012ff41,也就是说地址移动了一个字节,然后再将其强制类型转化为int*用ptr2来接收,如果机器是小端存储模式,那么a数组在内存中存储的方式就是01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00,移动一个字节之后的地址就变成了00 00 00 02 00 00 00 03 00 00 00 04 00 00 00,又因为ptr2是整形指针,解引用向后面访问4个字节,所以就得到了00 00 00 02,这个值在小端的存储模式下表示的值是 02 00 00 00,所以*ptr2的结果是2000000

 

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

解析:

如果仔细观察这个二维数组,可以发现它其实只有三个元素:1 3 5,而并非0 1 2 3 4 5,为什么呢?可以发现在{}里面用()分隔的元素,其实在()里面是一个逗号表达式,逗号表达式的结果是最后一个表达式的结果,所以(0,1)的结果是1,(2,3)的结果是3,(4,5)的结果是5,所以二维数组里面第一行的元素就是1,3,5,a[0]表示第一行的地址,将其存放在p里面,p[0]表示的就是第一行中下标为0的元素,所以p[0]的结果是1

五、笔试题5:

//代码运行结果
#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]);return 0;
}

解析:

指针-指针得到的是两个指针之间的元素个数

%p在打印的时候是直接将内存里面的值进行打印

int(*p)[4]表示的是一个数组指针,p指向的是一个整形指针,里面有四个元素,也就是意味着p+1只能跳过4个字节

 通过图来看&p[4][2]是低地址,而&a[4][2]是高地址,所以&p[4][2] - &a[4][2] = -4,-4如果使用%d的形式来打印就是-4,但是如果是以%p的形式来打印就得计算了:

-4的原码:10000000000000000000000000000100

-4的反码:1111111111111111111111111111111111011

-4的补码:1111111111111111111111111111111111100

所以在以%p的形式来打印-4时会打印-4的补码,四位的1是一个F,所以-4的补码转化为16进制就是FFFFFFFC,所以&p[4][2] - &a[4][2], &p[4][2] - &a[4][2]的结果分别为FFFFFFFC和-4

六、笔试题6:

#include <stdio.h>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跳过整个数组,然后强制类型转化为int*的指针赋给ptr1,所以*(ptr1 - 1)的结果是10

aa表示二维数组第一行的地址,+1表示跳过一行,指向了第二行,然后解引用拿到了第二行的元素,再进行强制类型转化为int*的指针赋给ptr2,所以ptr2指向的就是数组第二行的起始地址,所以*(ptr2 - 1)的结果是5

七、笔试题7:

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

解析:

以前提到过一个常量字符串放进指针里面的时候存放的是它的首字符的地址,所以a这个指针数组里面存放的是w、a、a的地址,然后使用一个二级指针来接收a,在这里的a表示数组首元素的地址,也就是w的地址,pa++跳过一个字符指向了a,然后*pa得到的就是a字符往后的元素,所以*pa的结果是at

八、笔试题8:

//代码的运行结果是什么?#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("%s\n", **++cpp);

++cpp是前置++,先++后使用,所以cpp指向了POINT,所以**++cpp的结果是POINT

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

这时的cpp指向的是c+2的地址,++cpp指向了c+1的地址,然后*++cpp得到了c+1的这块空间,c+1指向的是NEW,然后--,表示c+1的这块空间--,所以c+1指向的就变成了ENTER,然后再解引用拿到的是ENTER这个字符串,再+3表示ENTER跳过三个字节指向了ER,所以*-- * ++cpp + 3的结果是ER

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

这时的cpp指向的是c+1的地址,*(cpp - 2) = cpp[-2],所以cpp指向的是c+3的地址,然后解引用拿到了这块空间,这块空间里面存放的是FIRST,然后+3FIRST跳过三个字节,所以*cpp[-2] + 3的结果是ST

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

cpp[-1][-1]可以拆解为*(*(cpp-1)-1),这时的cpp指向的是c+3的地址,-1然后解引用得到的是c+2的这块空间,这块空间指向的是POINT,然后再-1解引用就得到了NEW,再+1跳过一个字节,所以cpp[-1][-1] + 1的结果是EW

程序运行结果为:

POINT
ER
ST
EW

本期分享到此结束,喜欢的老铁留下关注再走吧,万分感谢! 

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

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

相关文章

TiDB K8S

1、 命名空间 k create ns ti k create namespace tidb-admin k create namespace tidb-clusteralias kkubectl alias tik -n tidb alias tiak -n tidb-admin alias tick -n tidb-cluster2、 Helm安装 tidb-operator helm repo add pingcap https://charts.pingcap.org/ helm…

华为OD机试题【对称美学】用 Java 解 | 含解题说明

华为Od必看系列 华为OD机试 全流程解析+经验分享,题型分享,防作弊指南华为od机试,独家整理 已参加机试人员的实战技巧华为od 2023 | 什么是华为od,od 薪资待遇,od机试题清单华为OD机试真题大全,用 Python 解华为机试题 | 机试宝典本篇题目:对称美学 题目 对称就是最大的…

Rust学习总结之String

有编程经验的相信没少和字符串打交道&#xff0c;无论是C/C&#xff0c;还是现在比较流行的Python&#xff0c;字符串都是用的非常多的类型。在Rust中字符串类型同样有举足轻重的作用&#xff0c;几乎编码都离不开字符串。下面将详细学习Rust中的String类型。 一&#xff1a;创…

微信小程序——API promise化,全局数据共享,MobX,将Stroe中的成员绑定到页面中,在页面上使用Strore中的成员

一.API promise化1&#xff0e;基于回调函数的异步 API 的缺点默认情况下&#xff0c;小程序官方提供的异步 API 都是基于回调函数实现的&#xff0c;例如&#xff0c;网络请求的 API 需要按照如下的方式调用&#xff1a;缺点&#xff1a;容易造成回调地狱的问题&#xff0c;代…

25种代码坏味道总结

前言 什么样的代码是好代码呢&#xff1f;好的代码应该命名规范、可读性强、扩展性强、健壮性......而不好的代码又有哪些典型特征呢&#xff1f;这25种代码坏味道大家要注意啦 1. Duplicated Code &#xff08;重复代码&#xff09; 重复代码就是不同地点&#xff0c;有着相同…

为什么保存按钮那么像自动售货机?

高中生 Every Highschool Senior: I can’t wait to move out and go to college and Be on my Own. 每一个高中毕业生&#xff1a; 我等不及离开去大学&#xff0c;独立自我。 Everyone in College: 大学里的每个人&#xff1a; 评论区 Stoovin: The real world sucks. But…

LD_PRELOAD劫持(超详细篇)

目录 前提知识 环境变量 链接 LD_PRELOAD LD_LIBRARY_PATH ELF文件 /bin、/sbin、/usr/sbin、/usr/bin 漏洞复现 案例一(随机数劫持) 案例二(ls的劫持) 案例三(__attribute__&LD_PRELOAD劫持) 案例四(利用 LD_PRELOAD 绕过 Disable_Functions) 案例五(利用 er…

小白学Pytorch系列--Torch.nn API Pooling layers(3)

小白学Pytorch系列–Torch.nn API (3) 方法注释nn.MaxPool1d对由多个输入平面组成的输入信号应用1D最大池化。nn.MaxPool2d对由多个输入平面组成的输入信号应用二维最大池化。nn.MaxPool3d在由多个输入平面组成的输入信号上应用3D最大池化。nn.MaxUnpool1d计算MaxPool1d的偏逆。…

Zookeeper3.5.7版本—— Curator框架实现分布式锁案例

目录一、Zookeeper原生的 Java API 存在的问题二、Zookeeper原生的 Java API 存在问题的解决方式三、Curator框架实现分布式锁示例代码3.1、pom文件添加依赖3.2、示例代码3.3、Curator框架实现分布式锁测试一、Zookeeper原生的 Java API 存在的问题 会话连接是异步的&#xff…

Kubernetes为容器和 Pods 分配 CPU 资源

Kubernetes为容器和 Pods 分配 CPU 资源 一、指定CPU请求和CPU限制 1、创建一个命名空间&#xff08;namespace&#xff09; [rootmaster ~]# kubectl create namespace cpu-example namespace/cpu-example created2、编写yaml文件 要为容器指定CPU请求&#xff0c;需要在容…

STC32G 比较器及其应用编程

一 STC32G系列单片机寄存器简介STC32G系列单片机内部集成了一个比较器&#xff0c;其正极可以在P3.7、P5.0、P5.1、或者ADC的模拟输入通道间切换&#xff1b;而负极可以是P3.7或者内部BandGap经过OP的REF电压。通过配置分时复用可以实现多个比较器的应用。STC32G系列单片机的比…

MySQL数据库基础到进阶笔记整理包含事务、SQL优化、锁等内容

写在前面 本文是在学习MySQL数据库时整理的笔记&#xff0c;可供初学者学习 是在https://dhc.pythonanywhere.com/entry/share/?key12e4a7324f68371db3984d93e26e458962a4f0bc188ec23ec70637a4f3b4d58f 笔记基础上增加了一些内容以及后续的锁、InnoDB引擎等内容 课程参考b站黑…

Java数据结构与算法----搜索篇(DFS与BFS)

一.概念DFS&#xff08;Depth First Search&#xff09;深度优先搜索 和BFS&#xff08;Breadth First Search&#xff09;广度优先搜索 是两种广泛应用于搜索和遍历算法中的基本技术。这两种算法都涉及到搜索数据结构中的节点 。这里我们以二叉树为例&#xff0c;简单地图解一…

实验九 TSP问题

《算法设计与分析》实验报告 所在院系 计算机与信息工程学院 学生学号 学生姓名 年级专业 2020级计算机科学与技术 授课教师 彭绪富 学 期 2022-2023学年第一学期 提交时间 2022年10月26日 目 录 实验九-1&#xff1a;TSP问题 一、实验目的与要求 二…

【图解http】

目录了解web及网络基础TCP/IP协议族与HTTP关系密切的协议&#xff1a;IP、TCP和DNS各种协议与HTTP协议的关系URI和URLhttp协议HTTP是不保存状态的协议请求URI定位资源告知服务器意图的HTTP方法持久连接节省通信量HTTP报文编码提升传输速率压缩传输的内容编码分割发送的分块传输…

关于参加新星计划的收获

目录 作者简介 前言 一、新星计划介绍 二、新星计划创作目标 &#xff08;一&#xff09;创作打卡阶段第1周&#xff08;3/13-3/19&#xff09; &#xff08;二&#xff09;创作打卡阶段第2周&#xff08;3/20-3/26&#xff09; 三、参赛文章的构思与创作 &#xff08…

Go map 内存泄露

前言 在Go中, map这个结构使用的频率还是比较高的. 其实在所有的语言中, map使用的频率都是很高的. 之前在使用中, 一直都知道map的内存在元素删除的时候不会回收, 但一直没有仔细的研究为什么. 今天就来好好揣摩揣摩. func main() {m : make(map[int][128]byte)for i : 0; …

2023热门抖音权重查询小程序源码

2023热门抖音权重查询小程序源码 跟抖音上很火的一模一样&#xff0c;小程序适配优化。接口免费。小程序不是网页 修改教程: 1&#xff0c;如果想修改或者去除水印&#xff0c;直接删除或修改“index.html”12&#xff5e;22行 2&#xff0c;如果想修改logo&#xff0c;直接…

“全球首款旗舰”填补行业空白,两轮电动车技术创新为何只看绿源?

作者 | 曾响铃 文 | 响铃说 乒乓作为我们的“国球”&#xff0c;在数不清的体育赛事里书写辉煌战绩&#xff0c;也进一步被国人熟知、热爱。更难能可贵的是“国球”精神&#xff1a;“别人可能练了一千次&#xff0c;而我们却练了一万次”&#xff0c;冠军品质&#xff0c;奋…

MYSQL【基础篇】MYSQL 主要函数

MySQL中的函数主要分为以下四类&#xff1a; 字符串函数、数值函数、日期函数、流程函数 ​MySQL函数是MySQL数据库提供的内部函数。这些内部函数可以帮助用户更加方便的处理表中的数据 MySQL函数可以对表中数据进行相应的处理&#xff0c;以便得到用户希望得到的数据。这些函…