C++中指针&内存对齐详解

1.指针:很多的人在学完C++之后有相当一部分时间还是不知道指针是一个什么东西。我们来详细的解说一下。首先,我们需要明白一些基本的概念。在现在的计算机中,内存的编址方式是字节编址,也就是我们常说的字节寻址。在硬件上的反映就是内存条上的最小单元格子是一个字节,也就是一个Byte。而一个Byte有八个bit,也就是八位。我们知道,所有程序执行必须要被加载到内存,然后CPU在执行程序的时候从内存中加载数据来完成程序的运行。这其实在JAVA中有很好的体现,JAVA中有一套类加载机制,详细的解说了代码是如何被类加载器加载,这个我们以后再说。现在先看指针。指针我们理解的就是一个方向,这个东西他告诉你你想要找的东西在什么地方。那么有人可能会说,为什么要搞这么复杂,你直接给我存在这个地方不就行了,还搞什么中间商一样的东西,OK,这个问题大家可能在学高级语言的时候很疑惑,存指针也是存,存我真正想要的东西也是存,大家同时都要消耗时间,那么要你指针有什么用?这个疑惑我们马上解决。首先呢我们知道,指针是有值的,他也是一个类似于变量的东西,但是它的值不是别的,而是另一个东西的地址,有了这个地址你就可以找到这个地址存放的值。OK,我们来模拟一下这个过程。比如你是一个才来地大的新生,要去自己的寝室,这个时候你只是知道自己的目的地,但是不知道怎么走,然后抬头一看,一个路标:52栋的新生请直走,然后你照着这个路标找到了自己的寝室。这就是一个指针的作用,回到我们提出的问题,既然这个地方可以储存东西,那么要指针干嘛?你直接给我放这里不就行了,还让我找来找去的。我们回到刚才的场景,也就是说,你直接把宿舍楼给我建在这不就行了,我抬头就可以看见,还让我找来找去的。这显然是不可行的,宿舍怎么能够乱建呢?首先看到的应该是地大的牌面啊,怎么能是宿舍楼呢,对吧。可见指针还是很有必要的。那么我们如何从计算机的底层解释这个问题呢?我们都知道,CPU是直接从寄存器里面存取数据的,但是寄存器的大小和数量都是一定的,也就是说这里存放的东西不能太多,存一些关键的东西。比如我们有一个数组,访问这个数组的时候,你不能把数组全部放在寄存器内吧,我们只需要数组的名字,也就是首地址,然后按照字节寻址的规则就可以访问到数组中的任意元素。如果需要任意一个元素,我们把它加载到寄存器中使用,这样就会简便很多。这样看来,指针这个路标还是十分必要的。其实这也从侧面反映了数组的名字为什么要是首地址,不仅仅是数组名,函数名,类名,结构体名都是这样的。我们只需要加载它的基地址,就可以访问这个结构内部的任意元素。

2.指针的加减法:我们知道指针是有类型的,不同类型的指针指向的数据类型是不同的,好了,绕口令来了。尽管不同类型的指针指向的数据空间是不同的,但是他们的大小是相同的。其实也很好理解,很明显嘛,一个指针就是4个内存上的小格子,内存上的小格子大家都一样,都是一个字节,所以指针是四个字节大小。那么为什么指向的类型是不同的呢,这个也是比较复杂的问题,这里涉及到内存的对齐以及CPU读取内存的方式。就不再详细的讨论,其实做一个不恰当的比喻,所有的指针就可以看成一个面积相等的小长方形的格子,指针相加就是拿一些格子拼上来,减就是去掉一些格子。我们假设int类型的格子长为4,double长为8,那么一个int类型的指针+4,就是拿四个长为4的格子依次拼起来,那么其实这个比原来的地址偏移就是四个格子的长度,也就是16个字节。double类型的指针加4就是拿4个长度为8的长方形来拼,那么其实偏移就是32个字节。其实也是很好理解的。

3.最后是C++的内存布局以及内存对齐。其实这个东西我在前边的博客里面已经说过一个了,一个C++程序编译之后在内存中会产生分区,什么堆,栈,常量区什么的,以及如何计算一些复合数据类型占用的空间的大小,当然用sizeof()是很方便的,但是也要明白其中的道理。内存对齐根本的出发点是为了加快CPU的读取速度。详细的解析见:https://blog.csdn.net/weixin_41863129/article/details/80725570

猜你喜欢

转载自blog.csdn.net/weixin_41863129/article/details/83031278