好久不见,在外面玩了两周多,今天开始继续学习C语言。话不多说,现在开始。
一、内存和地址
1.1、内存
假设你住在一个公寓楼里,楼里有100个房间,但是房间没有编号,你的对象来找你玩,如果想找到你,就得挨个挨个的找,不方便。但是我们如果给每个房间编上号,比如101、201、301等等,你的对象知道的房间号,就能找到你了。把上面的例子对照进计算机语言中,又是如何呢?我们都知道,计算机CPU(中央处理器)在处理数据时,需要的数据是在内从中读取的,处理后的数据也会放回内存中,我们买电脑的时候,电脑内存是8GB/16GB/32GB等,那这些内存空间怎么搞笑的管理呢?
其实就是把内存划分为一个个的小单元,每个单元的大小取1个字节。一个比特位可以存储一个二进制的位1或者0。
其实每个内存单元,就相当于一个学生宿舍,一个字节能放8个比特,就好比一个房间能住8个同学
以下是一些换算:
1bit 比特位
2byte 字节
3KB
4MB
5GB
6TB
7PB
1byte=8bit
1KB=1024byte
1MB=1024KB
1GB=1024MB
1TB=1024GB
1PB=1024TB
1.2、地址
每个内存单元都有一个编号,相当于宿舍房间的门牌号。我们把计算机内存单元的编号称为地址。C语言中给地址取名为:指针
1.3、编址
因为内存中字节很多,要给内存进行编址。计算机中的编址并不是把每个字节的地址记录下来,而是通过硬件设计完成的。计算机内是有很多很多的硬件单元,而硬件单元是要互相协同工作的,但是硬件与硬件之间是相互独立的,为了能相互协同工作,就要用“线”连接起来。CPU和内存之间的也有大量的数据交互,两者也是用线连接起来的。我们现在只关心一种线,叫做地址总线。
简单理解一下:32位机器有32根地址总线,每根线只有两个状态,表示 0或者1(有无电脉冲),那么一根线就有两种含义,一次类推,32根线就有2^32种含义。
地址信息被下达给内存,在内存上,就可以找到该地址对应的数据,将数据通过数据总线传入CPU内存寄存器。
二、指针变量和地址
2.1、取地址操作符&
了解了内存和地址的关系,我们再回到C语言,在C语言中创建变量其实就是向内存申请空间,比如:
这个就是地址,如何取得a的地址呢?这里用到取地址操作符&,我们打印一下
2.2、指针变量和解引用操作符*
2.2.1、指针变量
我们通过取地址操作符&拿到的地址是一个数值,这个数值有时候也是需要存储起来的,方便后期使用的,那我们把这样的地址值存放在哪里呢?答案就是:指针变量中
比如:
指针变量也是一种变量,这种变量就是用来存放地址的,存放在指针变量中的值都会理解为地址。
2.2.2、拆解指针类型
我们看到的p的类型是int*,我们该如何理解指针类型呢?
int a = 10;
int * p = &a;
这里p左边写的int*,*是在说明p是指针变量,而前面的int是说明p指向的是整型(int)类型的对象。
如果有一个char类型的变量ch,ch的地址,要放在什么类型的指针变量中呢?答案是 char 类型的
2.2.3、解引用操作符
我们将地址保存起来,未来要使用,那怎么使用呢?这里就要引入解引用操作符 *
这里,我们先将a的地址储存在了p中,对p进行解引用操作,并赋值100,打印a的值,就是100了。
2.3、指针变量的大小
我们知道在32位机器中,一个地址就是32个bit位,需要4个字节才能存储。如果指针变量是用来存放地址的,那么指针变量的大小就得是4个字节的空间才可以。同理,64位机器就是8个字节大小。
不同类型指针变量在x64环境下:
x86环境下:
三、指针变量类型的意义
指针变量的大小和类型无关,只要是指针变量,在同一平台下,大小都是一样的,为什么还要有各各种各样的指针类型呢?
3.1、指针的解引用
对比下面代码,主要观察调试时内存的变化
开始的时候,n的地址是这个:
而运行到*p=0后,地址变为这个:
我们看下一段代码:
开始的时候,n的地址:
而运行到最后的地址:
通过这些我们看到,第一个代码将n的4个字节都变成了0,而第二个代码只是将第一个字节改为0
因此,指针的类型决定了对指针解引用的时候一次能操作几个字符。
3.2指针+-整数
先看一段代码,观察地址的变化 。
可以看出int*指针变量+1跳过了4个字节,而char*指针变量+1只跳过了一个字节。
今天就到这里了,明天见。