一文带你读懂指针

一文带你读懂指针


在初学学习指针的时候,难免会为其感到困惑,如指针数组、数组指针、指向指针的指针等形容常常让人头晕目眩,感到非常的玄乎

其实只要明白指针的本质,知道它在内存中的存在形式,那么就不会再为各种各样的指针感到困惑

指针的本质就是一个变量,其存放着指对象的地址

要搞清楚这些问题,首先需要对内存有所了解

一、内存长什么样?

我们的程序还有变量都存放在内存中,那么内存是长什么样的呢?

这里我用比较形象的比喻来说明,在32bit的CPU中,可以把内存想象成一栋大楼,每一层楼都有四个房间,每个房间都有一个门牌号,门牌号从左往右,从下到上依次递增,如下所示

在这里插入图片描述

上述中描述的对象对应到内存中如下

大楼指的是整块内存

房间指的是存储单元,每个存储单元存储一个字节(8bit)

门牌号指的是存储单元的地址,每个存储单元都有自己的一个地址,相邻两个存储单元地址相差1

为了后面讲解方便,后面我会将这幅图画为如下

在这里插入图片描述

前面的数表示这一层第一个存储单元的地址(十六进制表示),后面存储单元地址依次递增

二、变量在内存中的存储形式

在搞清楚内存长什么样子之后,我们再来看看变量在内存中存在形式

首先我们看一下char型变量是怎么存储的

我们知道char是占用一个字节,那么会在内存中,它将占用一个存储单元,如下所示

在这里插入图片描述

可以看到char在编号为0x00000001的存储单元,所以这个变量的地址为0x00000001

下面在来看看int形变量是怎么存储的

在32bit的CPU中,int类型的变量占用四个字节,所以它需要4个存储单元,另外其总是存储在4字节对齐的地址起始处,所以它在内存的存储形式如下

在这里插入图片描述

从图中可以看到,这个变量的起始存储单元编号为0x00000004,所以它的地址为0x00000004

在搞清楚变量在内存中的存储形式后,我们再来躺一躺指针在内存中的存储形式

三、指针在内存中的存储形式

为什么在学习指针在内存中的存储形式前,要先搞清楚变量呢?

因为指针的本质就是一个变量,你无需把它想象地有多么地玄乎,它就是一个变量,只是这个变量存储是其指向对象的地址

我们来看一看char*int*内存中有什么区别?

答案是没有区别,在32bit的CPU中,任何指针都是4个字节大小(占用4个存储单元),不管你是char*int*或者是double*,它们统统是4个字节大小,这也就意味着它们在内存中都是占用4个存储单元,所以它们在内存中的存在形式没有区别,如下图所示

在这里插入图片描述

上图中,变量中的指都为0,也就意味着指针想在指向空

那么char*int*的究竟有什么区别呢?

答案是编译器对它们的解释不同

编译器对char*变量的解释是,这个指针指向一个char形变量,也就是它所占用的存储单元存放的是一个char形变量的地址

编译器对int*变量的解释是,这个指针指向一个int形变量,也就是它所占用的存储单元存放的是一个int形变量的地址

在搞清楚指针在内存中的存储形式后,我们再来看一看所谓的指向xxx的指针究竟是怎么一回事

3.1 指向普通变量的指针

首先来看一个指向int型变量的指针

int a=1;
int* p = &a;

假设a的地址为0x00000004,p的地址为0x00000008,那么它们在内存中的存在形式如下所示

在这里插入图片描述

从图中可以看到,变量a的地址为0x00000004,其值为1,指针p的地址为0x00000008,其值为0x00000004,也就意味着它指向了a变量,这也就是所谓的指向int变量的指针在内存中的存在形式

指向char形变量的指针对应如下

char a = 1;
char* p = &a;

假设a的地址为0x00000005,p的地址为0x00000008,那么它们在内存中的存在形式如下所示

在这里插入图片描述

3.2 指向数组的指针

首先看数组在内存中的形式,数组是一块连续的内存,下面来看一看这个数组在内存中的表现形式

int array[3];

在这里插入图片描述

执行array表示第一个元素的地址

现在我们定义一个指向数组的指针

int array[3];
int* p = array;

其在内存中的形式如下

在这里插入图片描述

可以看到,它也仅仅是存储了数组首元素的地址,并没有什么特别

3.3 指针数组

所谓的指针数组是什么呢?

指针数组是一个数组,但是每个元素都是一个指针变量,如下定义

int* parray[3];

其在内存的表现形式如下

在这里插入图片描述

可以看到,每一个存储单元都可以存放一个int类型变量的地址

3.4 指向指针的指针

所谓指向指针的指针,意思是该指针里面存放的是另一个指针的地址

下面定义中,a是一个int型变量,p1是一个指向int型的指针,其指向a,p2是一个指向int型指针的指针,其指向p1

int a = 1;
int* p1 = &a;
int** p2 = &p1;

它们在内存中的形式如下

在这里插入图片描述

四、指针取值

在学习了指针在内存中的存储形式之后,你可能会好奇,在int*的指针和char*的指针取值的时候,是如何准确地操作到相应地存储单元呢?毕竟int为4个节点,char为1个节点

先看一下下面这段代码

char a = 1;
char* p = &a;

假设a的地址为0x00000005,p的地址为0x00000008,那么它们在内存中的存在形式如下所示

在这里插入图片描述

对于以下取值的代码,是如何进行的呢?

*p = 5;

编译器知道p是指向char类型的指针,而char占一个字节,所以在进行*p取值的时候,编译器会解释为,0x00000005存放着一个char型变量,其大小为1字节,所以只会操作到0x00000005处一个存储单元,然后对其按char型变量处理

同理对于int类型,其大小是4个字节,所以对于int型指针取值,会读取其所指地址处4个存储单元,然后按int型变量处理

到这里想必你对指针有了新的理解,本文到此也就结束了。

发布了107 篇原创文章 · 获赞 197 · 访问量 8万+

猜你喜欢

转载自blog.csdn.net/weixin_42462202/article/details/101679015