前言

  终于来到指针啦!如前篇末尾总结所说,这是你们马上要下大功夫的地方
  但是,就像我们上初中的时候,有人说函数难;我们上高中的时候,有人说导数、圆锥难;上大学的时候,有人说微积分难,事实上,别被吓到了,先勇敢尝试,迈过去了也就那么回事~


一、内存和地址

脱离内存和地址讲指针就是耍流氓!

内存

在讲解之前,先来个比方:

假设有一栋宿舍楼,把你放在楼里,楼上有100个房间,但是房间没有编号,你的一个朋友来找你玩,如果他想找到你,就得挨个房子去找,这样效率很低,但是我们根据楼层和楼层的房间的情况,给每个房间上号,如:
一楼:100、101、102…
二楼:200、201、202…

有了房间号的话,你的朋友就能很快找到你

如果把这个例子对照到计算中,又是怎么样的呢?
我们知道,CPU(中央处理器)在处理数据的时候,需要的数据是在内存中读取的,处理后的数据也会放回内存中,那我们买电脑的时候,电脑上内存是8GB/16GB/32GB等,那么这些内存该如何高效管理?
其实也是把内存分为一个个内存单元,每个内存单元的大小为1个字节,一个比特位可以放一个二进制位的1或者0

在这里,每个内存单元就相当于是一个学生宿舍,一个人字节空间里面能放8个比特位,就好比同学们住的八人间,每个人是一个比特位,每个内存单元也都有一个编号(这个编号就相当于是宿舍房间的门牌号)有了这个内存单元的编号,CPU就可以快速找到一个内存空间

生活中,我们把门牌号叫做地址,在计算机中我们把内存单元的编号也称为地址,C语言给这个地址起了一个新的名字,就叫做指针

一言以蔽之,内存单元的编号 == 地址 == 指针
在这里插入图片描述

究竟该如何理解编址

首先,我们必须要理解,计算机中有很多的硬件单元,而硬件单元是要互相协同工作的,所谓的协同,至少相互之间能够进行数据传递
但是硬件与硬件之间是互相独立的,那么如何通信呢?答案很简单,用“线”连起来
而CPU和内存之间也是有大量的数据交互的,所以,两者必须也用线连起来
CPU访问内存中的某个字节空间,必须知道它在内存中的位置,而因为字节很多,所以需要编址(如同宿舍很多。必须要编号一样自然),并且,计算机中的编址,并不是把每个字节的地址记录下来,而是通过硬件设计完成的
钢琴,吉他上面没有写上“都瑞咪发嗦啦”这样的信息,但演奏者照样能够准确找到每一个琴弦的每一个位置,这是什么原因?因为制造商已经在乐器硬件层面设计好了,并且所有的演奏者都知道。这质是一种约定俗成的共识!
而硬件的编址也是一样,我们可以简单理解为,32位机器有32根地址总线,每根线只有两态,表示0,1(电脉冲的有无),那么一根线,就有了2种含义,2根线就能表示4种含义,依次类推,32根地址线就能表示232种含义,每一种含义都代表一个地址
地址的信息被下达给内存,在内存中,就可以找到该地址对应的数据,将数据在通过数据总线传入CPU内寄存器
在这里插入图片描述

二、指针变量和地址

取地址操作符&

理解了内存和地址的关系,我们再回到C语言,在C语言中创建变量其实就是向内存申请空间

比如:
在这里插入图片描述

上述代码就是创建了整型变量a,内存中申请4个字节,用于存放整数10,其中每个字节都有地址,上图中4个字节的地址分别是:

0x000000109136F544
0x000000109136F545
0x000000109136F546
0x000000109136F547

那我们如何得到a的地址呢?
这里就得学习一个操作符&-取地址操作符
在这里插入图片描述

有意思的是,我们是如果&p打印a的地址,是打印出四个字节的地址中的首地址(低地址),也能理解,比如你家有四套房子,那你收一个快递的时候,也还是填一个地址,只要得到了首地址,其他三个地址也就很好求了

所以说&a是一个地址,那么假设变量pa = &a,那么pa是什么类型呢?
答案是int* ,即int* pa = &a; 其中pa就是指针变量,用来存放地址,即用来存放指针

我们也可以有一种形象的说法,pa指向a的第一个字节,这很形象,很有画面感
在这里插入图片描述

解引用操作符*

我们将地址保存起来,未来是要使用的,那怎么使用呢?
答案是在指针变量前面加个*

int a = 10;
int* pa = &a;
*pa = 20; // *是解引用操作符,*pa等价于a

pa就像一个代理人,联想到电视剧《狂飙》,强哥高启强想噶人,不能直接动手,跟老默说想吃鱼了,就是这个意思
至于你说为什么不直接a = 20; 难道计算机里面也会有类似安欣的存在限制了这一操作吗?哈哈,我们以后就会知道的,在这里先按下不表

指针变量的大小

指针变量是专门用来存放地址的,指针变量的大小是多少呢?取决于一个地址的存放需要多大空间!
在前面,我们了解到,32位机器假设有32根地址总线,每根地址线出来的电信号转换成数字信号后是1或者0,那我们把32根地址线产生的2进制序列当作一个地址,那么一个地址就是32个bit位,需要4个字节才能存储
同理64位机器,假设有64根地址线,一个地址就是64个二进制位组成的二进制序列,存储起来就需要八个字节(8 * 8 = 64),所以指针的大小都是4/8个字节

x86和x64环境下的输出结果:
在这里插入图片描述

32位平台下地址是32个bit位,指针变量大小是4个字节
64位平台下地址是64个bit位,指针变量大小是8个字节
注意指针变量的大小和类型是无关的,只要是指针类型的变量,在相同的平台下,大小都是相同的


总结

  指针我估计会出好几篇,第一篇就先不太难,也不太多,并且尽量以图形语言来展示,也卖了几个关子,回头见!

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部