文章目录
- 前言
- 一、内存和地址
- 内存
- 究竟该如何理解编址
- 二、指针变量和地址
- 取地址操作符&
- 解引用操作符*
- 指针变量的大小
- 总结
前言
终于来到指针啦!如前篇末尾总结所说,这是你们马上要下大功夫的地方
但是,就像我们上初中的时候,有人说函数难;我们上高中的时候,有人说导数、圆锥难;上大学的时候,有人说微积分难,事实上,别被吓到了,先勇敢尝试,迈过去了也就那么回事~
一、内存和地址
脱离内存和地址讲指针就是耍流氓!
内存
在讲解之前,先来个比方:
假设有一栋宿舍楼,把你放在楼里,楼上有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个字节
注意指针变量的大小和类型是无关的,只要是指针类型的变量,在相同的平台下,大小都是相同的
总结
指针我估计会出好几篇,第一篇就先不太难,也不太多,并且尽量以图形语言来展示,也卖了几个关子,回头见!