初学者对于结构体内存对齐与补齐的理解

来源:互联网 发布:mac怎么转换音频格式 编辑:程序博客网 时间:2024/04/30 07:17

1、问题提出:
刚开始学习结构体的时候,我们通常认为结构体

struct number_1{    int a;    int b;    int c;}st1;

占用空间为sizeof(st1.a)+sizeof(st1.b)+sizeof(st1.c)个,
(在vc++6.0中为4+4+4=12个)(为方便下文均以vc++6.0编译环境为例),实际操作中也是如此。道理却不是4+4+4=12的道理。

如:

struct number_2{    char a;    int b;    double c;}st2;

这里写图片描述
st2所占内存并非1+4+8=13个,而是16个>13个。这是为什么?

我们会发现,sizeof(st2)=16,刚好是double类型的二倍,这又是为什么?
我们将上例改为:

struct number_3{    char a;    int b;}st3;

这里写图片描述
会发现st3内存占用并非1+4=5个,而是sizeof(st3)=8个,刚好是int类型的二倍,这又是为什么??
了解过结构体内存对齐原则以后,初学时的问题才得以解决。

2、结构体在内存中的对齐原则:
结构体中包含有相同类型或不同类型的数据类型,如char(1字节),int(4字节),double(8字节),所以结构体内存出现了一个对齐原则:

结构体变量中元素是按照定义顺序一个一个放到内存中去的,但并不是紧密排列的。从结构体存储的首地址开始,每一个元素放置到内存中时,它都会认为内存是以它自己的大小来划分的,因此元素放置的位置一定会在自己宽度的整数倍上开始(以结构体变量首地址为0计算)。

即,当char a时,以char自身大小(一字节)划分,a占有了首地址0一个字节。但是当int b时,以int自身大小(四字节)划分,所以b从四字节的非负整数倍开始存储占用四个字节,由于首地址0已被占用,所以b从第四个地址开始占用四个字节。同理,当double c时,double也以自身大小(八字节)划分内存,而前八个(0——7)已被占用,故c从第八个地址开始占用八个字节。如下左图:
如果去掉中间定义的int b,st2仍然占16个字节。因为,double c时,首地址0已被占用,c不能从0(8的0倍)开始,就只能从8(8的1倍)开始。如下右图:

这里写图片描述 这里写图片描述

而且,double b之前空着的内存,在对齐下原则可以随意增加变量,内存是不会增加的。如下图:
这里写图片描述

3、内存的补齐原则:
当定义结构体为:

struct number_4{    char a;    int b;    char c;}st4;

时发现sizeof(st4)=12,而不是4+4+1=9。
这时候就牵扯到一个补齐原则:
在经过对齐原则分析后,检查计算出的存储单元是否为所有元素中所占内存最大的元素的长度的整数倍,是,则结束;若不是,则补齐为它的整数倍。

即,当4+4+1=9不是结构体中内存最大元素b的整数倍时,要补齐成其整数倍12。如下图左所示,如果将int换成double,sizeof(st4)=24为最大元素double的整数倍了。如下图右所示:

这里写图片描述 这里写图片描述

总结:
结构体在内存中的存储遵循着对齐与补齐的原则来存储。

2 0
原创粉丝点击