一、内存对齐目的与原理
1、内存对齐的目的
假如没有内存对齐机制,数据可以任意存放,现在一个int变量存放在从地址1开始的联系四个字节地址中,该处理器去取数据时,要先从0地址开始读取第一个4字节块,剔除不想要的字节(0地址),然后从地址4开始读取下一个4字节块,同样剔除不要的数据(5,6,7地址),最后留下的两块数据合并放入寄存器.这需要做很多工作。
现在有了内存对齐的,int类型数据只能存放在按照对齐规则的内存中,比如说0地址开始的内存。那么现在该处理器在取数据时一次性就能将数据读出来了,而且不需要做额外的操作,提高了效率。
2、原理
在32位编译环境下默认4字节对齐,在64位编译环境下默认8字节对齐。
例如:如下结构体:
struct s {
int a;
double b;
char c;
};
(1)在64位编译环境下,sizeof(s)=24。
解析: 首先你得知道各数据类型的字节长度:
char 1
int 4
double 8
那么其在内存中的存储如下:
从0的位置开始储存,int有4字节,默认8字节对齐,则下一个数据从第8位开始,double型正好8位,于是char接着从第16为开始,因为char型占一个字节,所以要补充7个字节空位。如果有下一个数据,将从第24位开始存储。
(2)在32位编译环境下,sizeof(s)=16。
么其在内存中的存储如下:
一共占16个字节。
二、修改对齐字节的方法:#pragma pack(对齐系数)
对齐系数:如1,2,4,8,16。如前所述:在不定义#pragma pack()的时候,在32位编译环境下默认4字节对齐相当于#pragma pack(4)
,在64位编译环境下默认8字节对齐相当于#pragma pack(8)
。
例如有如下结构体:
#include<stdio.h>
#pragma pack(8)
struct s {
int a;
double b;
char c;
}s;
int main()
{
printf("sizeof size = % d\n", sizeof(s));
}
测试结果
#pragma pack(1)-----------sizeof(s)=13
#pragma pack(2)-----------sizeof(s)=14
#pragma pack(4)-----------sizeof(s)=16
#pragma pack(8)-----------sizeof(s)=24
#pragma pack(16)-----------sizeof(s)=24
可以看到#pragma pack(8)
和#pragma pack(16)
时,结构体所占内存一样,这与我们之前的不一致。这是因为存在以下几条对其规则:
-
数据成员对齐规则:结构(struct)(或联合(union))的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员的对齐按照#pragma pack指定的数值和这个数据成员自身长度中,比较小的那个进行。
-
结构(或联合)的整体对齐规则:在数据成员完成各自对齐之后,结构(或联合)本身也要进行对齐,对齐将按照#pragma pack指定的数值和结构(或联合)最大数据成员长度中,比较小的那个进行。
-
结合1、2可推断:当#pragma pack的n值等于或超过所有数据成员长度的时候,这个n值的大小将不产生任何效果。
参考资料/文献:
https://zhuanlan.zhihu.com/p/30007037
https://www.jianshu.com/p/98fd45953dd8
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/73713.html