IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 指针以及二级指针和数组名转换指针的讲解 -> 正文阅读

[数据结构与算法]指针以及二级指针和数组名转换指针的讲解

一.指针的讲解

大家可能对于指针还是一个模糊的概念,下面我给大家讲解一下什么是指针:

指针是一个用于存储内存地址的变量;

比如说大家可能听说过指针变量

:char * p=&a(假设已经存在了变量a,&a拿出a的内存地址);

那么上面也就是拿出了a的内存地址存储于指针变量p中;

指针变量类型--常用的:double(8个字节),float(4个字节),long(4个字节),int(4个字节)

例如:

int arr[10]={0};

int * p=arr;(数组是可以直接拿出内存地址,但是这个内存地址,指的是数组首元素的内存地址);

p+1;(这里的的+1不是地址值+1而是跨越一个int类型的字节大小);

大家注意这里,为什么我给指针变量p+1后就由DC变成了E0呢(这里是使用16进制进行存储的可以参考我的另一篇文章,对于16进制的一些讲解);

因为加一后就跨越了一个int的大小的区域,也就是4个字节,所以就+4,所以根据16进制的运算导致了DC转换成为了E0;

指针的? ' * ' 这个东西又是干什么的呢?

这个在定义的时候是用于标识指针变量用的;

比如int a=9;

? ? ? ?int * b=&a;

上者是一个整数类型的变量,下者是一个存储整数a的内存地址的int类型的指针变量

大家注意一点:

变量拿出内存地址需要&符号

数组拿出内存地址是直接用数组名(注意,通过数组名拿出来的是首元素的内存地址)

二.数组名转换为指针

大家可能遇到了这个问题,"为什么我的这个数组名直接用sizeof测试时数组的字节大小,但是作为函数参数进行传递的时候再用sizeof测试,不管怎么测试都是4或者8字节(因为不同的编译器导致的指针大小不同);"那么这又是为什么呢?让我们来看一下下面的一个测试

?那么这是为什么,小伙伴可能就好奇了;

首先大家注意的一点是在第一个sizeof进行测试的是arr这个数组变量,数组变量也是有一个属于自己的内存地址,所以测试的是arr这个变量的大小,而当它作为参数进行传递的时候就不一样了,在c语言中传递的不是一整个数组,而是数组的首元素的内存地址,那么这个内存地址的传递后,为什么就是一个指针的大小了呢?

其实大家仔细回想一下,如果自己取出了一个变量后的内存地址会存储于哪里呢?

当然是指针变量中啊,正如有些人说指针就是内存地址

int a=0;

int * p=&a;

int arr[10]={};

int * p1=arr;

正如上所示,内存地址取出后都存储于指针之中了;

所以接收数组首元素的内存地址的形参就自然而然地成为了指针,这也就是为什么大家把数组名作为参数地时候就会变成指针地原因了;

三.2级指针

首先大家注意一点:

指针虽然使用于存储内存地址地,但是它本身也是一个变量,在内存中,也有着自己地内存地址,这也就是导致了二级指针的出现;

什么是二级指针呢?

二级指针是指向指针地指针,这样看起来挺难理解地;不过没有关系,只要明白了,再绕也能看懂

这个二级指针和二维数组来一起理解会比较好

首先在这里和大家先说清楚,所谓的指针也是一个变量,这也就是说他也有着自己的内存地址,同时还存储着其他变量的内存地址,同样数组虽然是存储着首元素的内存地址,但是数组本身也是一个变量,也有着自己的内存地址,所以因此也就出现了指向指针的指针的说法;

如下图

?配合代码上的注释相信也是有助于大家的理解

?代码第一行:

int zippo[4][2] = { {2,4},{6,8},{1,3},{5,7} };
?? ?//zippo是二维数组名同样是个变量,这也就意味着,它也有着自己的内存地址,他的值则是存储首元素(第一个一维数组的内存地址)地址,+1则是跨越了一个一维数组
?? ?printf(" ?zippo = ?%p , zippo +1 =%p \n",zippo,zippo+1);

大家注意:zippo他是一个二维数组,这个变量存储了首个一维数组的内存地址,(一维数组也是一个变量),zippo+1则是指跨越了一个一维数组的区域大小,如上图所示

?zippo = ?010FFBA0变成了zippo +1 =010FFBA8

这里可以很明显的看出来跨越了8个字节,也就是跨越了一个一维数组的大小

代码第二行:

?? ?//直接指向了这个一维数组这个变量,拿出的是一维数组存储的首元素的内存地址
?? ?printf(" ?zippo[0]=%p, ?zippo[0]+1=%p\n",zippo[0],zippo[0]+1);

zippo[0]是第一个一维数组变量;里面存储着第一个int变量的内存地址

后面+1则是在第一个元素的内存地址的基础上再跨越了一个int类型的区域大小

?zippo[0]=010FFBA0变成了zippo[0]+1=010FFBA4;

代码这一部分:

?? ?//首先zippo[0]指得是首个一维数组这个变量,这个变量里面存储首元素的内存地址,进行解析后找到对于的变量值
?? ?printf(" ?*zippo[0]=%d",*zippo[0]);
?? ?printf(" ?**zippo=%d",**zippo);

**这就是这里面可能有些麻烦的地方了;不过没关系,多看看就简单了

首先看到上面的额第一行:

首先是指二维数组的第一个一维数组,由于内部存储着首元素的内存内存地址所以再使用*进行解引

就得到了整数值:*zippo[0]=2;

然后再看**zippo这里面*有2个看起来有点唬人,没关系,我们一起来看看

首先zippo是一个变量,有着属于自己的内存地址(?&zippo = ?007BFBF8),同样它的内部也存储着其他变量,例如一维数组的内存地址,然而一维数组也是一个变量,也同样存储着另一个变量的内存地址

所以*zippo就是解引zippo内部存储的内存地址,找到对应的变量,也就是首个一维数组;

在使用*,也就是**zippo也就是解引一维数组的存储的内存地址,找到对应的变量,也就是正如上图所见的2!也就是首个一维数组的首元素!!!!!

到了这里再提示一下

int (*p)[2]=zippo;

这里面可以这样理解:

传递过来的是二维数组的"内存地址",那么接收内存地址的就是指针所以先使用(*p),根据指针指向的一维数组,确定一维数组的元素多少个,再决定int?(*p)[2],这个[]中的大小

若有不当之处,还望指教谢谢

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-03-08 22:48:16  更:2022-03-08 22:51:30 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 13:29:11-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码