快速理解内存对齐以及#pragma pack

导读:本篇文章讲解 快速理解内存对齐以及#pragma pack,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

一、内存对齐目的与原理
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)时,结构体所占内存一样,这与我们之前的不一致。这是因为存在以下几条对其规则:

  1. 数据成员对齐规则:结构(struct)(或联合(union))的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员的对齐按照#pragma pack指定的数值和这个数据成员自身长度中,比较小的那个进行。

  2. 结构(或联合)的整体对齐规则:在数据成员完成各自对齐之后,结构(或联合)本身也要进行对齐,对齐将按照#pragma pack指定的数值和结构(或联合)最大数据成员长度中,比较小的那个进行。

  3. 结合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

(0)
小半的头像小半

相关推荐

极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!