内存对齐(Struct)

来源:互联网 发布:固结实验数据 编辑:程序博客网 时间:2024/05/29 12:28

内存对齐是一个硬件问题,是为了高效访问数据,尽管这样会浪费少量空间。
对齐就是数据项只能存放在地址是数据项整数倍的内存位置上,即你访问一个8字节的double数据时,地址只允许是8的整数倍,所以一个double可以存储在24,8008,32786,但不能存储在1006(因为无法被8整除)

而系统一般都有自己的默认对齐数,vs下默认为8,linux下默认为4
可以通过#pragma pack()来修改默认对齐数,注意只能调小,不能调大
下面直接通过实例来探究:

struct A{    char a;    double b;    int c;};

这个结构体的大小是多少呢?如果你只是打眼一看就觉得1+8+4=13,那就大错特错了,首先char是1个字节没问题,关键是第二个是double,它的地址必须可以被8整除,所以就导致它会偏移7个字节,最后再加上int,即8+8+4=20,但是默认对齐数是8,你整个要可以被默认对齐数整除,所以就变成24。
这里写图片描述
为什么会这样呢,可以想一下这个结构体中各个变量在内存中的分布情况,如图:
这里写图片描述

为了证实我画的这个图,我给a,b,c分别赋值,如果分析的没错的话,那么a只占一个字节,那么它后面的7个字节便会由系统自动填充,b是double占用8个,int占4个,后面4个自动填充。

直接运行程序来看内存情况:
这里写图片描述
这里的cc就是系统自动填充的默认值,也就说明确实是这样进行内存对齐的。

说到这里还没完,如果一个结构体当中包含有其他结构体那该如何对齐呢?再来看一个例子。

struct B{    char b1;    struct A obj;    struct A obj1[2];    char* d;};

那这个结构体多大呢?是不是觉得不知道这个struct A obj的偏移量是多少?
一个结构体的对齐数,是结构体中最大变量的大小,即obj的对齐数,是struct A中的double,也就是8,现在来算一下。

char占一个字节,obj对齐数是8,obj1是一个数组包含两个struct A,d是一个指针,32位下占4个字节。
1+7+24+2*24+4=84,因为要和默认对齐数8对齐,所以自动填补到88,要被8整除呢。

如果懂了的话,快去linux下试一下,或者将默认对齐数改为4,自己计算一下,然后再跑一下程序吧!