内存对齐计算方法(偏移量)

ba0efa564bde4779b6c5d85d1e3e3f4f.jpeg

2b7e3d4cef754a6eb32953107929889a.jpeg内存对齐简单来讲就是把一个数据存放到内存中,其内存的地址要与数据自己大小为整数倍。 处理器在执行指令去操作内存中的数据,这些数据通过地址来获取。 当一个数据所在的地址和它的大小对齐的时候,就说这个数据对齐了,否则就是没对齐。

内存对齐是以空间换时间的方法,计算机一次就可以把存储的数据提取出来,极大提高了效率。

 首先以结构体为例来阐明是如何计算的。

 2b7e3d4cef754a6eb32953107929889a.jpeg结构体对齐规则:

1.1

第一个成员的地址在结构体变量偏移量为0的地址处。

1.2 

其中对齐数=编译器默认的一个对齐数与该成员大小的较小值。(vs默认为8)

1.3 

其他成员变量依次要按照对齐数的整数倍的地址处来存放。

1.4 

结构体总体的大小要为最大对齐数的整倍数。(每一个成员变量都有自己的对齐数,与1.3描述的对象不一样)

1.5

如果一个结构体里面包含一个结构体,把其看作一个成员就行(但其整体对齐数不能看作一个对齐数来比是否为最大对齐数)。

 简单看个例子:

#include <stdio.h>
struct s1
{
	char a;
	int b;
	char c;
};
struct s2
{
	char a;
	char b;
	int c;
};
struct s3
{
	int c;
	char a;
	char b;
};
int main()
{
	struct s1 q = { 0 };
	struct s2 w = { 0 };
	struct s3 e = { 0 };
	printf("%d\n", sizeof(q));
	printf("%d\n", sizeof(w));
	printf("%d\n", sizeof(e));
	return 0;
}

结果:

12
8
8

D:\VS\Project4\x64\Debug\Project4.exe (进程 13452)已退出,代码为 0。
按任意键关闭此窗口. . .

分析:

三个结构体其中包含的成员一样,但为什么打印的结果不一样呢?这就用到了内存对齐了。

先看s1在内存中真实的存储:

                a
  
  
  
                 b
                 b
                 b
                 b
                 c
  
  
 

12刚好是最大对齐数4的整数倍,所以此处即为完整内存大小。

                  结束

  

注释:
1. char类型所占字节为1,比默认对齐数8要小,所以对齐数是1。

2. int类型所占字节为4,比默认对齐数8要小,所以对齐数是4。

3.所以最大对齐数就是4。

4. 而其他成员变量依次要按照对齐数的整数倍的地址处来存放。所以要往下偏移(浪费)3个节大小,再往下就是4,来存放int类型,存完int类型时为8,

5. 再来一个char类型,对齐数为1,所以现在内存大小为9,

6. 此外还要满足是最大对齐数的整数倍,所以还要再偏移(浪费)3个字节大小,即为12。

 

于是s2在内存中真实的存储:

                     a
                     b
                      
  
                      c
                      c
                      c
 

                     c

                   结束

  
  

注释:

1. 一个char类型,对齐数为1,所以存放在了0地址处,

2. 再来一个char类型,对齐数为1,所以现在内存大小为2,

3. 接下来是int类型,所以要往下偏移2个字节大小,再存放int的4个字节,

4. 现在内存大小为8,刚好是最大内存数4的整数倍。即为8。

5. 同理可得s3在内存中真实的存储情况,有兴趣的小伙伴可自行研究一下哈。

当结构体里面包含一个结构体呢?

如:

#include <stdio.h>
struct s1
{
	char a;
    int  b;
	char c;
};
struct s2
{
	struct s1 s;
	char a;
	char b;
	int c;
};

int main()
{
	printf("%d\n", sizeof(s2));
	return 0;
}

结果:

20

D:\VS\Project4\x64\Debug\Project4.exe (进程 9968)已退出,代码为 0。
按任意键关闭此窗口. . .

分析:

1. 先来排结构体s,一个char类型,一个int类型,在一个char类型。最大对齐数是4,所以最后结果是12。

2. 再来一个char类型,对齐数为1,直接在后面存就行,所以现在内存大小为13。

3. 再来一个char类型,内存大小变为14。

4. 因为最大对齐数为 4, 14 不是4的倍数,所以会往后偏移(浪费)2个字节大小,变为16,再来存放int的4个字节,即为20。

此外补充两个知识点:

一:

#pragma pack (4)

表示设置默认对齐数为4。

#pragma pack ()

表示取消设置的默认对齐数。

二:

offsetof 可计算偏移量大小。

size_t offsetof(struct name, nember name);

(成员相当于类型的偏移量)。

 

 

 

ba0efa564bde4779b6c5d85d1e3e3f4f.jpeg

 

  • 19
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 31
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 31
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

洁洁!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值