C语言 -- 深入理解指针(一)
1.内存和地址
1.1 内存
- 定义 :在计算机的组成结构中有一个很重要的部分是存储器。它是用来存储程序和数据的部件。
- 我们知道计算上CPU(中央处理器)在处理数据的时候,需要的数据是在内存中读取的,处理后的数据也会放回内存中,那我们买电脑的时候,电脑上内存是8GB/16GB/32GB等,那这些内存空间如何高效的管理呢?
1.其实也是把内存划分为一个个的内存单元,每个内存单元的大小取1个字节。一个字节里面能放八个比特。每个内存单元也都有一个编号,有了这个内存单元的编号,CPU就可以快速找到一个内存空间。
2.在计算机中我们把内存单元的编号也称为地址。C语言中给地址起了新的名字叫:指针。
3.所以我们可以理解为:内存单元的编号 == 地址 == 指针
关于对内存有着更进一步的了解,我们可以看图:如下
计算机中常见的单位(补充):
⼀个比特位可以存储⼀个2进制的位1或者0
1.2 究竟该如何理解编址
- CPU访问内存中的某个字节空间,必须知道这个字节空间在内存的什么位置,而因为内存中字节很多,所以需要给内存进行编址(就如同宿舍很多,需要给宿舍编号一样)。
- 计算机中的编址,并不是把每个字节的地址记录下来,而是通过硬件设计完成的。
- 首先,必须理解,计算机内是有很多的硬件单元,而硬件单元是要互相协同工作的。所谓的协同,至少相互之间要能够进行数据传递。
- 但是硬件与硬件之间是互相独立的,那么如何通信呢?答案很简单,用"线"连起来。
请看下图
假设CPU要想去内存中拿数据(值)时,怎么拿呢?
先通过控制总线向内存中读一个数据,读的数据地址在内存哪里呢?
- 地址总线会给出信息,如果在32位机器上就会有32根地址总线,每一根地址线上都会有一个电信号,高电频或低电频这样的一个电信号,我们把这样的电信号转化成数字信号的时候就是1 或者 0,每根地址线上都给这样的信号话,那32根地址线上就会产生一个二进制序列来作为地址,因为有32根地址总线 所以就能产生2^32种二进制序列,每一种都代表一个地址。
我们要去读一个数据时,地址信息被下达给内存,在内存上,就可以找到该地址对应的数据,将数据在通过数据总线传入CPU内寄存器。
2. 指针变量和地址
2.1 取地址操作符(&)
首先我们先看下面代码:
其中每个字节都有地址,我们如何能得到a的地址呢?
这里就得学习一个操作符(&)-取地址操作符
在看如下代码:
打印出的a地址是以 16进制的形式输出的。展开的形式不以二进制形式展示,因为二进制位太长了,观察起来不方便。
1.&a取出的是a所占4个字节中地址较小的字节的地址。
2.虽然整型变量占用4个字节,我们只要知道了第一个字节地址,顺藤摸瓜访问到4个字节的数据也是可行的。
2.2 指针变量和解引用操作符(*)
2.2.1 指针变量
- 那我们通过取地址操作符(&)拿到的地址是一个数值,比如:0x006FFD70,这个数值有时候也是需要存储起来,方便后期再使用的,那我们把这样的地址值存放在哪里呢?答案是:指针变量中。
如下:
- pa 是指针变量 - 存放地址 - 地址又被称为指针,指针变量是用来存放指针的
- 指针 和 指针变量的区别
2.1 指针就是地址,指针变量就是一个变量 -->存放地址- 口头语:说指针一般就是指针变量
指针变量也是⼀种变量,这种变量就是⽤来存放地址的,存放在指针变量中的值都会理解为地址。
2.2.2 如何拆解指针类型
我们看到pa的类型是 int* ,我们该如何理解指针的类型呢?
解析下面代码:
- int * 是 指针变量pa的类型
- 这里的 * 说明pa是指针变量
- 最前面的int是在说明pa指向的对象是int类型的
如下图:
那如果有一个char类型的变量ch,ch的地址,要放在什么类型的指针变量中呢?
char ch = ‘w’;
pc = &ch;//pc 的类型怎么写呢?
答案是 : char * pc = &ch;
2.2.3 解引用操作符
- 我们将地址保存起来,未来是要使用的,那怎么使用呢?
- 在现实生活中,我们使用地址要找到一个房间,在房间里可以拿去或者存放物品。
- C语言中其实也是一样的,我们只要拿到了地址(指针),就可以通过地址(指针)找到地址(指针)指向的对象,这里必须学习一个操作符叫解引用操作符(*)。
1 .* pa 的意思就是通过pa中存放的地址,找到指向的空间,
2. * pa其实就是变量a;所以*pa = 0,这个操作符是把a改成了0.
有同学肯定在想,这里如果目的就是把a改成0的话,写成 a = 0; 不就完了,为啥非要使用指针呢?
其实这里是把a的修改交给了pa来操作,这样对a的修改,就多了一种的途径,写代码就会更加灵活,后期慢慢就能理解了。
2.3 指针变量的大小
- 指针变量是用来专门存放地址的,大小取决于