【C语言进阶】 指针强化练习

news2024/12/23 8:43:24

目录

  • 题目一
  • 题目二
  • 题目三
  • 题目四
  • 题目五
  • 题目六
  • 题目七
  • 题目八

题目一

下面这段代码的执行结果是?

int main()
{
	int a[5] = { 1, 2, 3, 4, 5 };
	int* ptr = (int*)(&a + 1);
	printf("%d,%d\n", *(a + 1), *(ptr - 1));
	return 0;
}

 解决这种数组与指针相结合的问题,关键在于认清代码中的数组名到底表示什么。一般情况下:

  • 数组名表示首元素地址

两个例外:

  • sizeof(数组名)计算的是整个数组的大小(单位是字节)
  • &数组名取到的是整个数组的地址,&数组名+1跳过一整个数组

 所以上述代码中的&a得到的就是整个数组的地址,如果用一个指针变量来存储这个地址的话,指针变量的类型是:nt (*) [5]&a+1跳过一整个数组,表示紧接着a数组后面的一个地址,这个地址还是表示一个数组的地址,然后把这个地址强制转换成整型指针,此时这个地址表示一个整型的地址。虽然&a+1从一个数组的地址变成了一个整形的地址,但是它们在数值上却没有发生任何变化,那把一个数组地址强制转换成整型地址的意义在哪呢?意义在于:不同类型的地址访问到的内存空间大小会有所不同,比如:一个整型地址只能访问到从当前地址开始,连续的四个字节的内容(一个地址指向一个字节);一个字符的地址只能访问到当前地址所指向的一个字节的内容;一个数组的地址可以访问到整个数组所占用的字节内容。把一个数组的地址强制转换成整型的地址,就好比把酒店中的总统套房改造成一个标间,虽然它们的门牌号都相同,但由于它们的房间类型发生了,所以里面房间的大小就会发生改变,从原来200平的总统套房,变成如今只有90平的标间。对地址类型的转变,主要体现在:地址加减整数上。比如:一个整型地址+1,会跳过4个字节(这里+1就表示跳过一个整型,一个整型就对应4个字节);一个字符型地址+1,会跳过一个字节;上述代码中的数组地址+1,会跳过20个字节(数组中有5个整型原素,一个整型对应4个字节,5个整型就对应20个字节,这20个字节也就是a数组的大小)。当了解了这些知识点以后,再来看上面的代码,*(a + 1)其中a是数组名,表示首元素地址,也就是一个整型的地址,+1跳过一个整型,所以a+1表示数组中第二个元素的地址,也就是2的地址,然后解引用,就会得到2。再看*(ptr - 1),此时的ptr指向数组a后面紧接着的地址,并且已经被强制转换成了整型指针,所以ptr-1会跳过一个整型,指向数组中的5,解引用就会得到5
 所以最终这段代码会在屏幕上打印出:2 5

在这里插入图片描述

题目二

下面这段代码的执行结果是?

struct Test
{
	int Num;
	int pcName;
	short sDate;
	char cha[2];
	short sBa[4];
}*p;
//假设p 的值为0x100000。 如下表表达式的值分别为多少?
//已知,结构体Test类型的变量大小是20个字节
int main()
{
	p = (struct Test*)0x100000;//强行让p等于0x100000
	printf("%p\n", p + 0x1);
	printf("%p\n", (unsigned long)p + 0x1);
	printf("%p\n", (unsigned int*)p + 0x1);
	return 0;
}

 这里的p本质上是一个结构体类型的指针,这个结构体的大小是20个字节,+1跳过一个结构体的大小,也就是+20个字节,其中的0x表示十六进制,20的十六进制是14,所以这里的p+0x1就是:0x100000+0x14=0x100014(unsigned long)p把指针变量p强制类型转换成整型变量,此时p的值0x100000就不再表示地址了,而是表示一个整数0x100000(unsigned long)p + 0x1就是我们小学就学过的整数加法,结果等于0x100001(unsigned int*)p把结构体类型的指针强制类型转换成整型指针,此时p的值0x100000还表示一个地址,但表示的是一个整型的地址,不再是结构体类型的地址,所以+1跳过一个整型,也就是+4个字节,(unsigned int*)p + 0x1就是0x100000+0x4=0x100004。最终%p打印的是地址,所以结果为:00100014、00100001、00100004

题目三

下面这段代码的执行结果是?

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拿到的是整个数组的大小,+1跳过一个数组的大小,上面已经相依讲过,这里不再赘述。本题需要注意的有:ptr[-1]就等价于*(ptr-1),还有就是(int*)((int)a + 1)这里a本来表示数组首元素地址,这里先把其转换成整型,然后+1,这里进行的是整数加法,然后再把这个结果转换成整型指针,放到ptr2这个指针变量里面,ptr2的指向如下图所示。还需注意的是,在我当前的编译环境下,数据是按照小端字节序的模式存到内存里面的,所以在从内存中读数据的时候也许注意。%x是以十六进制的形式打印。最终结果是:4,2000000

在这里插入图片描述

题目四

下面这段代码的执行结果是?

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] = { 1,3,5 };。还需注意a[0]是二维数组a中第一行一维数组的数组名,数组名又表示首元素地址,所以此时p里面存的是数组中a[0][0]也就是元素1的地址,p[0]就等价于*(p+0),所以最终的结果是:1

题目五

下面这段代码的执行结果是?

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 [4]。也就是说p指向一个整型数组,这个数组有四个元素,其次a是二维数组名,表示首元素的地址,二维数组的首元素是a[0],也就是二维数组中第一行那个一维数组,所以a表示首元素地址,就是二维数组中第一行那个一维数组的地址,它的类型是int(*)[5],把这个类型的地址放到类型为int(*)[4]的指针变量里面,是可以强行放进去的。&p[4][2]其中p[4][2]就是&*(*(p+4)+2),这里需要注意p指向的数组只有四个元素,所以p+1跳过四个元素,这里p+4就会跳过16个元素。
在这里插入图片描述
本题最终的结果就是:FFFFFFFC、-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;
}

 本题需要注意的是:&aa拿到的是整个二维数组的地址&aa+1跳过整个二维数组,它的类型是int [2][5],然后把这个地址强制转换成int*型;aa数组名表示首元素地址,是第一行一维数组的地址,aa+1表示第二行一维数组的地址,解引用得到第二行的一维数组也就是aa[1]aa[1]是第二行一维数组的数组名,数组名表示首元素地址,也就是aa[1][0]的地址,aa[1][0]就是6,这里也就是6的地址,所以这原本就是一个整形的地址,(*(aa + 1))前面的强制类型转换就可有可无。本题最终的结果就是:10、5

题目七

下面这段代码的执行结果是?

int main()
{
	char* a[] = { "work","at","alibaba" };
	char** pa = a;
	pa++;
	printf("%s\n", *pa);
	return 0;
}

 本题需要注意的是:首先a是一个字符指针数组,说明a数组里面存放的是字符的地址,而字符串常量的值就是首字符的地址,所以a数组里面存放的就是"work"'w'的地址、"at"'a'的地址、"alibaba"'a'的地址,数组名a表示首元素地址,也就是a[0]的地址,a[0]里面存放的是'w’的地址,所以a[0]的地址就是'w'的地址的地址,也就是指针的地址,所以这用了一个二级指针变量pa来接收。char** pa应该这样来理解:首先* pa中的*告知我们pa是一个指针变量,char*告诉我们这个指针变量指向一个char*类型的数据,所以对pa++,会跳过一个char*类型的数据,此时pa指向a数组中的第二个元素a[1],也就是说此时pa指向'a'的地址,所以对pa解引用就会得到'a'的地址,然后以%s的格式打印,最终在屏幕上打印出:at
在这里插入图片描述

题目八

下面这段代码的执行结果是?

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

在这里插入图片描述
**++cpp++cppcpp就指向cp[1], 第一次解引用得到cp[1]这块空间里面的内容,也就是c[2]的地址,第二次解引用得到c[2]这块空间里面的内容,c[2]里面存的是'P'的地址,所以第一次打印出: POINT*-- * ++cpp + 3,首先++cpp,此时cpp指向cp[2],然后解引用得到cp[2]这块空间里面的内容,也就是c[1]的地址,然后- -,c[1]的地址是一个char*类型的地址。所以- -跳过一个char*类型的数据,此时得到的就是c[0]的地址,解引用得到c[0]这块空间里面的内容,也就是得到'E'的地址,这是一个字符的地址,+3跳过3个字符,此时得到"ENTER"中第二个'E'的地址,所以第二次打印出:ER*cpp[-2] + 3中的cpp[-2]就表示*(cpp-2)cpp当前指向cp[2],所以cpp-2指向cp[0]*(cpp-2)得到cp[0]这块空间里面的内容,也就是得到了c[3]的地址,所以cpp[-2]表示的就是c[3]的地址,*cpp[-2]得到c[3]这块空间里面的内容,也就是得到了'F'的地址,这是一个char类型(字符)的地址,所以*cpp[-2] + 3会跳过3个字符,此时表示"FIRST"'S'的地址,最终打印出来:STcpp[-1][-1] + 1中的cpp[-1]表示*(cpp-1)cpp当前指向cp[2],所以*(cpp-1)最终得到c[2]的地址,cpp[-1][-1]表示:*(*(cpp-1)-1),其中*(cpp-1)-1得到c[1]的地址,所以*(*(cpp-1)-1)最终得到c[1]这块空间里面的内容,也就是得到'N'的地址,这也就说明cpp[-1][-1] 表示的就是'N'的地址,所以cpp[-1][-1] + 1就表示:"NEW"'E'的地址,最终打印出:EW

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

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

相关文章

【Leetcode面试常见题目题解】2. 无重复字符的最长子串

题目描述 本文是LC第3题:无重复字符的最长子串。 题目描述如下 给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。 举例 输入: s “abcabcbb” 输出: 3 解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。 输入:…

html实现酷炫的公司年会抽奖(附源码)

文章目录1.设计来源1.1 主界面1.2 抽奖效果1.2 中奖效果2.效果和源码配置2.1 动态效果2.2 员工信息配置2.3 奖品信息配置2.4 抽奖音效配置2.5 源代码源码下载作者:xcLeigh 文章地址:https://blog.csdn.net/weixin_43151418/article/details/128640998 ht…

AI绘画日漫欧漫动态表情换脸游戏风生成红包封面流量主小程序开发

AI绘画日漫欧漫动态表情换脸游戏风生成红包封面流量主小程序开发 因全网AI绘画大量小程序被封禁下架。只有采用合规稳定运营引擎。 文生图图动日漫图生欧漫图转动图人物表情变脸换脸3D动漫集成7大AI制图模式 支持个人模式和企业支付。趣味AI制图支持流量主。 打造一款适合个人…

uniapp 画中画悬浮窗(视频) Ba-VideoPip

简介(下载地址) Ba-VideoPip 是一款画中画方式的视频悬浮窗插件。支持点播、直播;支持官方、三方播放器无缝切换;支持动态刷新(如切换视频或进度)。 支持点播、直播支持官方、三方播放器无缝切换支持动态…

【unity3D】Collider碰撞器组件

💗 未来的游戏开发程序媛,现在的努力学习菜鸡 💦本专栏是我关于游戏开发的学习笔记 🈶本篇是unity的Collider碰撞器组件 Collider碰撞器组件▶碰撞器类别▶Box Collider▶Sphere Collider▶Box Collider 2D▶Composite Collider 2…

Aspose.Words for .NET Crack 23.1.0

Aspose.Words for .NET Crack Aspose.Words 及其产品系列是一组 Word 文档,它们处理 API 以创建、编辑、打印、阅读和稍后转换所有格式化的 Word 文档和文件格式,就在 .NET、Java、Android 中、Cloud、SSRS、SharePoint 以及最后但并非最不重要的 Jasper…

【fpdlink显示】DS90UB948关于941连接948 GPIO调试问题

1. 前言 使用一个941连接2 948显示: 941的GPIO0/1/2/3到前948的GPIO0/1/2/3和941的D_GPIO0/1/2/3到948的GPIO0/1/2/3。 设置gpio3输出,则941的D_GPIO3设置高,而948的gpio3设置不高; 但设置gpio3输入后,看到941的D_GPIO3跟随948的gpio3变化。 2. 原理图连接 3. 测试代码…

通过图像了解 Git

我受到Nico Riedmann 的 Learn git concepts, not commands 的启发,我用我自己的方式总结了 git。当然,我也通过阅读官方文档来补充它。从系统结构上理解git,让git更有趣。我最近对 git 上瘾了,以至于我正在创建自己的 git 系统。…

Java集合常见面试题(一)

集合概述 Java 集合, 也叫作容器,主要是由两大接口派生而来:一个是 Collection接口,主要用于存放单一元素;另一个是 Map 接口,主要用于存放键值对。对于Collection 接口,下面又有三个主要的子接…

HarmonyOS智能座舱体验是怎样炼成的?立即查看

目录 一、智能座舱的人因设计理念 1.驾驶场景“2s内安全交互” 2.屏幕信息科学布局 3.屏幕1:2比例特色分屏 二、如何对座舱应用高效设计开发 1.基础要求 2.开发禁止 3.更佳体验 1.音频类应用快速接入 2.手机服务卡片快速适配 三、软硬件联合打造优秀体验 1.小憩模式 2.K歌体验 …

RepVGG:让VGG风格的ConvNets再次伟大

论文地址:https://arxiv.org/abs/2101.03697 我们提出了一种简单但功能强大的卷积神经网络结构,该模型在推理时类似于VGG,只有33的卷积和ReLU堆叠而成,而训练时间模型具有多分支拓扑结构。训练时间和推理时间结构的这种解耦是通过…

李宏毅ML-局部最小值与鞍点

局部最小值与鞍点 文章目录局部最小值与鞍点1. Optimization 没有做好是因为什么?2. Local Minima or Saddle Point?3. 如何解决 Saddle Point?1. Optimization 没有做好是因为什么? 观察下图,随着 update 的次数增加&#xff0…

MFC或C/C++中如何判断目录存在,文件/文件夹存在,亦或是文件夹存在,文件存在

判断的方式太多太多,这里暂时列举5中方式。 在文章开始之前,由于需要用到CString转char功能,所以先介绍一个CString转char的方法: 想知道更多参见CString与char *互转总结 由于本文使用的Unicode编码模式,所以如下&…

链动2+1商业模式的玩法是怎么样的?

如果你感觉自己的产品卖不掉,很可能是因为缺乏一种成功业务模型,因此我们来聊聊运营商业运营模式理论:从一个销售产品到一个商业运营模式的高速发展,我们不能把它简单的当做是一种营销方法,也就是一种产品的营销方法。…

六、MySQL 数据库练习题1(包含前5章练习题目及答案)

文章目录一、数据库概述练习题二、MySQL 环境搭建练习题三、查询练习MySQL 数据库练习题(包含前5章所有知识点及答案) 前置知识: 一、数据库开发与实战专栏导学及数据库基础概念入门 二、MySQL 介绍及 MySQL 安装与配置 三、MySQL 数据库的基本操作 四、MySQL 存储…

PrimalSQL 2023 Crack

PrimalSQL 2023 使数据库查询开发和测试变得轻而易举,无论您的数据库类型或供应商如何。 通过单个工具支持多个数据库提供程序。 Access、SQL Server、SQL Server Compact、MySQL、Oracle、ODBC、OLEDB、Sybase 等。 使用Visual Query Builder构建复杂的查询。 使…

Steam/CSGO游戏搬砖1月行情分析及应对方法

Steam/CSGO游戏搬砖1月行情分析及应对方法 这几天,我看很多地方还在对外宣称说这个项目有百分之十几,二三十的利润率,多么无敌和暴利! 天啦 ,这些人为了能割到小白的韭菜真是无所不用其极,什么牛都能吹得出…

外包和外派

前言 简单介绍下人们常说的外包是什么,应届生未出社会没有经验,避免求职过程中的一些坑。 文章目录前言一、什么是外包?1、简介1、项目外包2、人力外包二、外包公司有哪些?三、优缺点1、优点2、缺点四、选择一、什么是外包&#x…

海思SS928V100开发(2)镜像烧录

1. 开发板没有uboot 在\01.software\pc\ToolPlatform下,打开烧写工具ToolPlatform如下: 选择 “烧写eMMC”,并添加fastboot,kernel,rootfs,如下图: 然后点击 烧写,进入烧写模式(注意:检查串口选择是否正确,传输方式选择 网口): 烧写完成uboot,kernel和rootf后的…

流媒体协议之RTMP详解

流媒体协议之RTMP详解 文章目录流媒体协议之RTMP详解1 RTMP概述2 RTMP交互过程2.1 握手协议2.2 RTMP分块(chunk)2.3 协议控制消息(Protocol Control Message)2.4 RTMP Message Format2.5 不同类型的RTMP Message2.6 RTMP Massage和…