c/c++内存对齐详解

来源:互联网 发布:淘宝的宝贝卖点 编辑:程序博客网 时间:2024/06/08 14:19

如有错误,欢迎批评指正

引言:前一段时间在做图像处理的时候,当我想把图像头信息填充到自定义的结构体中时,发现文件的内容与填充到结构体中的内容不一致,经过反复查资料,看博客,最后才恍然大悟,原来问题出在了结构体是需要内存对齐的。一万个兴奋,有木有大笑。现把结构体内存对齐相关问题整理如下,希望能够对看到这篇博客的童鞋们有所帮助。

一、什么是自然对齐

内存是按照字节划分的,按理说数据可以存放在内存中的任意位置,其实并不然。如果一个变量的内存地址正好是其所占字节的整数倍,它就被称自然对齐。例如在32位机器中,如果int变量在内存中的地址为0X00000008,那么他就是自然对齐的。

二、为什么需要字节对齐

CPU访问数据的方式是字节对齐的根本原因。假如一个int型的变量存放在地址为0x00000002中,那么cpu将会分两次读取内存,第一次读取0x00000002~0x00000003中的内容,第二次读取0x00000004~0x00000005中的内容,然后将这两次读取的数据按照高低字节组合起来,假如放在地址为0x00000005中,那就更惨,cpu需要分三次读取数据,增加了cpu的负担浪费了时间。如果放在自然对齐的地址上,则cpu一次就可以将数据读取。想必大家都懂为何要字节对齐了吧!!!

三、结构体中的字节对齐

有一结构体,定义如下:

struct  A

{

char  str;

short  count;

int  time;

}

问题1:自己想一想sizeof(A)是多少?(8)

struct  A

{

char  str;

int  time;

short  count;

}

问题2:sizeof(A)又是多少?(12)

在回答这个问题之前,我们先看看结构体对齐的两条重要的原则:

①结构体数据成员的字节对齐:

结构体中的第一个数据成员放在偏移地址为0X00处,以后每个数据成员的对齐按照#pragma pack指定的数值(或默认值)和这个数据成员类型长度中,比较小的那个进行。在上一个对齐后的地址处开始寻找能被当前对齐数值整除的地址。

②结构体整体的对齐

除了结构体中的数据成员要对齐之外,结构体本身也要对齐,这体现在在最后一个数据成员的后面补0。假设#pragma pack指定的数值(或默认值)为n,结构体数据成员中类型最大的为m,则以二者的最小值进行对齐。

对于问题1:

struct  A

{

char  str;//偏移地址:0x00

short  count;//偏移地址:0x02

int  time;//偏移地址:0x04

}

故结构体数据成员对齐后所占字节为8,又VS默认对齐为n=4,结构体数据成员类型中最大m=4,min(n,m) = 4,8是4的整数倍,故sizeof(A)=8;

对于问题2:

struct  A

{

char  str;//偏移地址:0x00

int  time;//偏移地址:0x04

short  count;//偏移地址:0x08

}

故结构体数据成员对齐后所占字节为10,又VS默认对齐为n=4,结构体数据成员类型中最大m=4,min(n,m) = 4,10不是min(n,m)的整数倍,故需要在结构体最后一个成员后填补0(两个字节),因此sizeof(A) = 12。

看完之后不知道小伙伴们有什么感悟。。。。。。


0 0
原创粉丝点击