内存对齐

今天,Mayuyu意外地写了如下两段代码:

 

片段一:

#include <iostream>
#include <string.h>
#include <stdio.h>

using namespace std;

struct Node
{
    char a;
    int x;
    char b;
};

int main()
{
    cout<<sizeof(Node)<<endl;
    return 0;
}


片段二:

#include <iostream>
#include <string.h>
#include <stdio.h>

using namespace std;

struct Node
{
    char a;
    char b;
    int x;
};

int main()
{
    cout<<sizeof(Node)<<endl;
    return 0;
}


 

可以很容易看出,上面的两段代码只是结构体内的变量的排列顺序不同。输出结果却分别是128

 

为什么会这样?Mayuyu迷惑了,根据Mayuyu从C语言中学到的一个char在内存中占1字节,一个int占4字节。那

么sizeof(Node)应该是6字节才对啊。为什么变量排列顺序不同,会导致结构体在内存中所占总空间不同? 这一

切要从C语言中内存对齐说起。

 

那么,接下来你就该问,什么是内存对齐? 接下来Mayuyu将一一给你讲述。

 

我们知道,内存是一个连续的块,它是以n个字节对齐一个单位的,一般默认情况下n = 4,除非你自己重新定义对

齐单位的字节数。如下图:

 

 

在C语言或者C++中,都会遵循内存对齐。比如对于片段一的代码来说,先是char a占用了最上边的一格,然后

int x申请4字节内存,但是发现在上面的一个单位也就是4字节里面还剩余3字节,已经小于4字节,那么这3字

节不会被申请,而会申请下一个单位,刚好4字节,满足条件,继续char b也会占一个字节,但是最小的单位是

4字节,那么剩下的3字节也算在内,如下图:

 

 

所以,这样下来就必定是12字节,我们也就不会奇怪会输出12了,同样的道理我们也会得到片段二的结果为8。

 

也就是说最小的分配单位就是4字节,当然这里的“4”实际上是可以自己指定的,只是系统默认是4而已。比如我们

完全可以自己指定一个单位的大小。比如指定为一个单位的大小为1字节。如下:

 

#include <iostream>
#include <string.h>
#include <stdio.h>

using namespace std;

#pragma pack(push);
#pragma pack(1);

struct Node
{
    char a;
    int x;
    char b;
};

#pragma pack(pop);

int main()
{
    cout<<sizeof(Node)<<endl;
    return 0;
}

 

这样我们就可以输出我们真正期望的值6。

 

讲到了这里,你或许会问C语言中内存对齐的单位为4字节,这样做岂不是很浪费。比如片段一,本来6字节就够了,

但是我们却足足申请了12字节,大大地浪费啊。那么Mayuyu将会告诉你,你说得没错,但是你忽略了另一个因素,

那就是效率。

 

假如我们不进行内存对齐,把内存申请后,在取数的时候CPU会非常痛苦。因为如果一个数越两个内存单位,我们

要取出它,CPU会访问两次内存。对于片段一的代码如果不进行内存对齐就是这样,取出x的值CPU就会访问两次内

存,如果进行内存对齐,只需访问一次。

 

实际上,内存对齐的原因主要有以下两个:

 

(1)平台原因:并不是所有的硬件平台都能访问任意地址的任意数据。

(2)性能原因:就是上面所说的,减少CPU的访问内存次数,性能也就会相应提高。

 

从上面可以看出,我们可以指定内存对齐一个单位的字节数,而这里的字节数一般都是取1,2,4,8,16等等。一般系

统默认是4字节为一个单位,因为这样可以把效率和内存使用情况折中。

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值