C++内存对齐问题

    在上一篇写道位域大小的时候,简短的提到了内存对齐的问题,而本文就将对内存对齐做个简单的说明,让各位脑中有个简单的概念。

    说内存对齐,我觉得还是应该先说说为什么需要有内存对齐,大部分的参考资料都是如是说的:1、平台原因(移植原因):不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。2、性能原因:数据结构(尤其是栈)应该尽可能地在自然边界上对齐。原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;而对齐的内存访问仅需要一次访问。

    内存对齐的概念则是:各种数据类型在空间上按一定规则排列,而不是顺序地一个接一个排列。提到一定规则,引入规则之前,先来做个概念解释:每个特定平台的编译器都有一个默认的“对齐系数”,也可叫对齐模数。而这个对齐系数,我们是可以通过代码来修改的:#pragma pack(n), 其中n就是对齐系数。下面就引入对齐规则:

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

#include <iostream>
using namespace std;

#pragma pack(4)
struct s1 {
    char a;
    char b;
    int i;
};
#pragma pack()

struct s2 {
    char a;
    int i;
    char b;
};

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

以gcc4.8.1为例,gcc4.8.1的默认对齐系数为4,我们仔细观察上述例子,a和b都放在i前,a和b都是char型,占一个字节,i是int型,占四个字节,我们运行后可以发现,s1的大小是8,s2的大小是12。参考上面的对齐规则1,我们知道a放在偏移量为0的地方,而b的大小和对齐系数相比,b的大小是小的,所以b的对齐应该按照b的大小来排列,与a同属于同一个对齐区域,而i为4字节,与对齐系数大小相等,就按对齐系数大小来排列,放于下一个对齐区域。由此,我们可以知道8是如何得来的了,a和b在第一个对齐区域,第一个对齐区域大小为4,i则独占第二个对齐区域,大小也为4,所以得出s1大小为8。对于s2,同样的分析方法,a独占第一个对齐区域,b独占第三个对齐区域,i独占第二个对齐区域,大小都为4,所以加起来大小就为12。

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

对于第二点,我们可以通过这样一段代码进行验证:

struct s3 {
    char a;
};

struct s4 {
    char b;
};

struct s5 {
    s3 _x;
    s4 _y;
    int i;
};

   3.结合12可推断:当#pragma packn值等于或超过所有数据成员长度的时候,这个n值的大小将不产生任何效果。

 内存对齐是个复杂的东西,本文也只是做个简单介绍,更多的情况还需要去查阅各类文档、论文,本文就不再一一详述了。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值