c/c++内存对齐详解
2016-02-25 11:28
169 查看
如有错误,欢迎批评指正
引言:前一段时间在做图像处理的时候,当我想把图像头信息填充到自定义的结构体中时,发现文件的内容与填充到结构体中的内容不一致,经过反复查资料,看博客,最后才恍然大悟,原来问题出在了结构体是需要内存对齐的。一万个兴奋,有木有
![](http://static.blog.csdn.net/xheditor/xheditor_emot/default/laugh.gif)
。现把结构体内存对齐相关问题整理如下,希望能够对看到这篇博客的童鞋们有所帮助。
一、什么是自然对齐
内存是按照字节划分的,按理说数据可以存放在内存中的任意位置,其实并不然。如果一个变量的内存地址正好是其所占字节的整数倍,它就被称自然对齐。例如在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。
看完之后不知道小伙伴们有什么感悟。。。。。。
引言:前一段时间在做图像处理的时候,当我想把图像头信息填充到自定义的结构体中时,发现文件的内容与填充到结构体中的内容不一致,经过反复查资料,看博客,最后才恍然大悟,原来问题出在了结构体是需要内存对齐的。一万个兴奋,有木有
![](http://static.blog.csdn.net/xheditor/xheditor_emot/default/laugh.gif)
。现把结构体内存对齐相关问题整理如下,希望能够对看到这篇博客的童鞋们有所帮助。
一、什么是自然对齐
内存是按照字节划分的,按理说数据可以存放在内存中的任意位置,其实并不然。如果一个变量的内存地址正好是其所占字节的整数倍,它就被称自然对齐。例如在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。
看完之后不知道小伙伴们有什么感悟。。。。。。
相关文章推荐
- 图片整理
- C++11新特性总结(枚举+继承+左右值引用+变长模板)
- 使用C++实现虚幻4通电游戏
- 挑7
- 字符串最后一个单词的长度
- c++中的左值与右值
- strcmpi
- C++Primer第5版读书笔记(第2章)
- C/C++变量命名规则,个人习惯总结
- [置顶] c语言入门项目之4.0——利用for循环求1/2-2/3+3/4-...+19/20
- C++学习笔记:多态的实现原理
- c++11随机数产生器default_random_engine
- C语言基本数据类型简介
- 浅谈 C++ 中的 new/delete 和 new[]/delete[]
- C++ 基础教程(结合虚幻4)
- C++11之生产者消费者
- C语言知识整理(一)
- 1043. Is It a Binary Search Tree (25)
- C语言格式占位符
- 【C++】判断本地文件是否存在