深入解剖指针(6)

news2025/2/26 5:01:39

个人主页(找往期文章包括但不限于本期文章中不懂的知识点):我要学编程(ಥ_ಥ)-CSDN博客

目录

二维数组

指针运算笔试题解析


接着上篇文章的题目(所有的代码运行环境若无特殊说明,则都是VS2022,x64环境下运行)

二维数组

#include <stdio.h>
int main()
{
	int a[3][4] = { 0 };
	//sizeof(数组名),这是单独的数组名,表示整个数组
	printf("%zd\n", sizeof(a));//48 = 3*4*4
	//a[0][0]就是二维数组的第一行第一列的元素
	printf("%zd\n", sizeof(a[0][0]));//4
	//在学习二维数组的时候,我们是把每一行看成一个一维数组,
	//那些一维数组就是二维数组的元素,而a[0]就是第一行的一维数组
	//然后就会发现整个a[0]是那个一维数组的数组名,sizeof(数组名)
	printf("%zd\n", sizeof(a[0]));//16 = 4*4
	//sizeof(数组名+1),这个数组名就表示首元素的地址,再+1,就是第二个元素的地址&a[0][1]
	printf("%zd\n", sizeof(a[0] + 1));// 4/8
	//* &a[0][1]<-->a[0][1]
	printf("%zd\n", sizeof(*(a[0] + 1)));//4
	//a这里是二维数组的数组名,表示的是首元素的地址,而二维数组的元素是一维数组
	//a<-->&a[0],再+1,就是&a[1]
	printf("%zd\n", sizeof(a + 1));// 4/8
	//* &a[1]<-->a[1],这是第二行的一维数组的数组名
	printf("%zd\n", sizeof(*(a + 1)));//16 = 4*4
	//a[0]是数组名,&a[0],拿到的是第一行的一维数组的地址,再+1,就是第二行的地址
	printf("%zd\n", sizeof(&a[0] + 1));// 4/8
	//根据上面就可以知道整个解引用之后拿到的是第二行的所有元素
	printf("%zd\n", sizeof(*(&a[0] + 1)));//16 = 4*4
	//这里的a是首元素的地址,也就是第一行的地址,解引用之后就拿到了第一行所有元素
	printf("%zd\n", sizeof(*a));//16 = 4*4
	//虽然这个已经越界访问了,但是还是可以拿到第四行的所有元素
	printf("%zd\n", sizeof(a[3]));//16 = 4*4
	return 0;
}

总结:数组名的意义: 1. sizeof(数组名),这里的数组名表示整个数组(单独只有数组名的时候),计算的是整个数组的大小。 2. &数组名,这里的数组名表示整个数组,取出的是整个数组的地址。 3. 除此之外所有的数组名都表示数组首元素的地址。 

指针运算笔试题解析

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

题目2:

//在X86环境下
//假设结构体的⼤⼩是20个字节
#include <stdio.h>

struct Test
{
	int Num;
	char* pcName;
	short sDate;
	char cha[2];
	short sBa[4];
}*p = (struct Test*)0x100000;

int main()
{
	printf("%p\n", p + 0x1);
	printf("%p\n", (unsigned long)p + 0x1);
	printf("%p\n", (unsigned int*)p + 0x1);
	return 0;
}

题目3:

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

题目4: 

//假设是x86环境
#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;
}

 题目5:

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

题目6:

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

题目7: 

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

**++cpp,由于++(前缀)的优先级大于*,所以先算++的值(注意++会改变cpp本身的值,++cpp<-->cpp = cpp+1),本来cpp指向的是c+3,现在++,就变成了指向c+2的地址了,再解引用就是拿到c+2的,而c+2指向的是P的地址的地址,再解引用就是拿到P的地址,打印之后就算是POINT。


*--*++cpp+3,同样先看看操作符的优先级,先算++,我们前面的cpp已经是指向c+2了,再++,就变成了指向c+1,再解引用,就拿到了c+1,再--,--(c+1)的结果就是c,而c指向的E的地址的地址,再解引用就是拿到了E的地址,再+3就是拿到了E的地址,打印之后的ER。

*cpp[-2]+3,因为[ ]的优先级大于*,所以先算cpp[-2]<-->*(cpp-2),cpp指向的时c(原来的c+1)的地址,*(cpp-2)就是拿到F的地址的地址,再解引用就是拿到F的地址,+3就是S的地址了,打印之后就是ST。

cpp[-1][-1]+1<-->*(*(cpp-1)-1)+1,*(cpp-1)拿到的是P的地址的地址,*(*(cpp-1)-1)拿到的N的地址,再+1,就是拿到E的地址,打印之后就是EW。

和指针相关的题目就是转换为内存来理解,即画图来分析。 

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

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

相关文章

公益src | 一次简单的验证码绕过

本文由掌控安全学院 -好好好 投稿 1、在漏洞平台&#xff0c;公益SRC上&#xff0c;找一个网站&#xff0c;找到登录处 2、抓包&#xff0c;发现密码明文&#xff0c;放到Repeater&#xff0c;多次G&#xff4f;&#xff0c;发现没有验证码&#xff0c;也不限制次数 &…

CBAM注意力机制详解(附pytorch复现)

简介 论文原址&#xff1a;1807.06521.pdf (arxiv.org) CBAM&#xff08;Convolutional Block Attention Module&#xff09;是一种卷积神经网络模块&#xff0c;旨在通过引入注意力机制来提升网络的表示能力。CBAM包含两个顺序子模块&#xff1a;通道注意力模块和空间注意力…

视频拉流推流技术梳理

概况 视频的整个流程主要分为推流和拉流 摄像头场景&#xff1a; 摄像头捕捉视频画面&#xff0c;推流到服务器&#xff0c;服务器分发到CDN&#xff0c; 客户端从CDN地址拉流&#xff0c;客户端进行播放 直播场景&#xff1a; 主播通过手机&#xff0c;电脑等客户端&…

强化学习(六)时序差分

时序差分&#xff08;TD&#xff09;是强化学习的核心&#xff0c;其是蒙特卡罗&#xff08;MC&#xff09;和动态规划&#xff08;DP&#xff09;的结合。 1、TD 预测 TD 和 MC 都是利用经验来解决预测问题。一种非平稳环境的一般访问蒙特卡罗方法是 V ( S t ) ← V ( S t …

力扣-H指数

问题 给你一个整数数组 citations &#xff0c;其中 citations[i] 表示研究者的第 i 篇论文被引用的次数。计算并返回该研究者的 h 指数。 根据维基百科上 h 指数的定义&#xff1a;h 代表“高引用次数” &#xff0c;一名科研人员的 h 指数 是指他&#xff08;她&#xff09…

android开发平台,Java+性能优化+APP开发+NDK+跨平台技术

开头 通常作为一个Android APP开发者&#xff0c;我们并不关心Android的源代码实现&#xff0c;不过随着Android开发者越来越多&#xff0c;企业在筛选Android程序员时越来越看中一个程序员对于Android底层的理解和思考&#xff0c;这里的底层主要就是Android Framewok中各个组…

【Linux深入剖析】再续环境变量 | 进程地址空间

&#x1f4d9; 作者简介 &#xff1a;RO-BERRY &#x1f4d7; 学习方向&#xff1a;致力于C、C、数据结构、TCP/IP、数据库等等一系列知识 &#x1f4d2; 日后方向 : 偏向于CPP开发以及大数据方向&#xff0c;欢迎各位关注&#xff0c;谢谢各位的支持 目录 1.环境变量再续1.1 和…

图书管理系统(使用IO流实现数据的读取和写入)--version4.0

目录 一、项目要求&#xff1a; 二、项目环境 三、项目使用的知识点 四、项目代码 五、项目运行结果 六、项目难点分析 图书管理系统--versions1.0&#xff1a; 图书管理系统--versions1.0-CSDN博客文章浏览阅读981次&#xff0c;点赞29次&#xff0c;收藏17次。本文使用…

Encoding, Encryption, Tokenization 傻傻分不清楚

Encoding, Encryption, Tokenization 傻傻分不清楚 本文转自 公众号 ByteByteGo&#xff0c;如有侵权&#xff0c;请联系&#xff0c;立即删除 今天来聊聊编码 (Encoding), 加密 (Encryption) 和 令牌化 (Tokenization) 的区别。 编码、加密和标记化是三种不同的流程&#xff…

游泳耳机哪个牌子质量好?4大高口碑产品推荐入手

游泳耳机作为一种专业的水上音频装备&#xff0c;能够使游泳者在游泳过程中享受音乐的同时保持安全和舒适。随着科技的发展&#xff0c;市面上涌现出许多品牌和型号的游泳耳机&#xff0c;但是其中哪个牌子的质量更好呢&#xff1f;下面这篇文章将为大家介绍四大热门口碑产品&a…

项目流程图

实现便利店自助付款项目 服务器&#xff1a; 1、并发服务器&#xff08;多进程、多线程、IO多路复用&#xff09; 2、SQL数据库的创建和使用&#xff08;增删改查&#xff09; 3、以模块化编写项目代码&#xff0c;按照不同模块编写.h/.c文件 客户端&#xff1a; 1、QT客户端界…

dolphinscheduler伪集群部署教程

文章目录 前言一、配置免密登录1. 配置root用户免密登录2. 创建用户2.1 创建dolphinscheduler用户2.2 配置dolphinscheduler用户免密登录2.3 退出dolphinscheduler用户 二、安装准备1. 安装条件2. 安装jdk3. 安装MySQL4. 安装zookeeper4.1 zookeeper单机部署4.1.1 zookeeper3.1…

js 手写深拷贝方法

文章目录 一、深拷贝实现代码二、代码讲解2.1 obj.constructor(obj)2.2 防止循环引用 手写一个深拷贝是我们常见的面试题&#xff0c;在实现过程中我们需要考虑的类型很多&#xff0c;包括对象、数组、函数、日期等。以下就是深拷贝实现逻辑 一、深拷贝实现代码 const origin…

扫码看视频的效果怎么做?在电脑上制作视频活码只需3步

怎么做扫码看视频的效果呢&#xff1f;通过二维码来储存视频并用来做展示用途&#xff0c;是现在很常见的一种二维码应用类型&#xff0c;这种方式可以有效的提升内容的快速传播&#xff0c;而且用户体验也比较好。 那么如何通过视频二维码生成器的功能来制作自己的二维码图片…

提升媒体文字质量:常见错误及改进措施解析

在现代媒体出版中&#xff0c;文字质量直接影响着信息的传递效率和准确性。近期&#xff0c;中国产业报协会全国行业报质检办公室对中央及国家机关主管的84家行业报纸进行了质量检查&#xff0c;发现了一系列共性的文字使用错误。本文旨在深入探讨这些错误&#xff0c;并提出改…

Springboot中ApplicationContextInitializer的使用及源码分析

文章目录 一、认识ApplicationContextInitializer1、ApplicationContextInitializer的作用2、认识ApplicationContextInitializer接口3、ApplicationContextInitializer的常用用法&#xff08;1&#xff09;注册BeanFactoryPostProcessor&#xff08;2&#xff09;注册Applicat…

关于StartAI本地部署相关问题解答

很多小伙伴们都有接入自己本地SD的需求&#xff0c;对此小编整理了一些相关问题~ 一、本地部署相关条件 对于想要本地部署的小伙伴要了解&#xff0c;相对于使用StartAI试用引擎本地部署更加考验电脑硬件配置备噢~ 流畅使用要nvidia显卡&#xff0c;6g以上显存&#xff08;最…

Google发布Genie硬杠Sora:通过大量无监督视频训练最终生成可交互虚拟世界

前言 Sora 问世才不到两个星期&#xff0c;谷歌的世界模型也来了&#xff0c;能力看似更强大(嗯&#xff0c;看似)&#xff1a;它生成的虚拟世界自主可控 第一部分 首个基础世界模型Genie 1.1 Genie是什么 Genie是第一个以无监督方式从未标记的互联网视频中训练的生成式交互…

浅析前端的堆栈原理以及深浅拷贝原理

浅析前端的堆栈原理以及深浅拷贝原理 首先来看一个案例 const obj {name:hzw,age:18 } let objName2 obj objName2.age 12 console.log(obj,objName2) // {name: hzw, age: 12} {name: hzw, age: 12}这里是不是很奇怪&#xff0c;为什么&#xff0c;为什么我改变objName2的…

使用 Gradle 版本目录进行依赖管理 - Android

/ 前言 / 在软件开发中&#xff0c;依赖管理是一个至关重要的方面。合理的依赖版本控制有助于确保项目的稳定性、安全性和可维护性。 Gradle版本目录&#xff08;Version Catalogs&#xff09;是 Gradle 构建工具的一个强大功能&#xff0c;它为项目提供了一种集中管理依赖…