struct自然边界上的内存对齐

    内存对齐大多数情况对程序员是透明的,是由编译器自动处理。在C里面允许我们干预内存对齐。而由于内存对齐的原因,巧妙的设计结构体也是非常必要的。
   关于内存对齐问题,字、双字和四字在自然边界上不需要在内存中对齐,对字、双字和四字来说自然边界分别是奇数地址,可以被2整除地址,和被4整除地址。而数据访问未对齐的内存,处理器需要作两次内存访问,而对齐的内存只作一次访问;这是原因之一,另外不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。因此为提高程序性能,数据结构尤其是栈应尽可能在自然边界上对齐。
    一个字起始地址是奇数(当然偶数也行)但却没有跨越字边界,被认为是对齐的。下面来看个例子:
struct TestStruct1
{
       char c1;
       short s;
       char c2;
       int i;
};
    如果紧凑排列,c1地址是0,那么s:为1; c2:为3;i为4,整个结构体大小为8;但很可惜,s为2,c2为4;i为8;而整个结构体大小为12。编译器将未对齐的s,c2,i成员后移,使之对齐到自然边界上,从而也让大小由8变成了12。
如果是这样的结构:
struct TestStruct2
{
       char c1;
       char c2;
       short s;
       int i;
};
    c1地址如果是0,接下来到c2,由于是一个字自然边界是奇数,所以对齐不需后移,故c2地址为1;到s,双字自然边界被2整除,也对齐,不需后移,地址为2;到i,四字自然边界被4整除,不需后移,地址为4;结构体大小为8。
接下来再看一个例子:
struct TestStruct3
{
       char c1;
       int j;
       char c2;
};
    c1地址如果是0,接下来由于j四字自然边界被4整除,而没有对齐,故地址后移3位,为4;到c2,一字自然边界是奇数不用后移,地址为8,整个结构体应该为9,但很可惜,其实大小为12。
为什么呢,原因是前面是int,申请的大小为4,以后申请的大小应该都为4。这样解释貌似合理。
再看一个例子:
struct TestStruct4
{
       char c1;
       int j;
       char c2;
       char c3
};
    其中c1,j,c2和TestStruct3一样,到c3,由于c2申请的4个只用了1个,而又有c3自然边界是奇数,故可以不用后移,地址为9,当然结构体大小也不变为12。
    若结构体变成这种:
struct TestStruct5
{
       char c1;
       int j;
       char c2;
       short i;
};

    则在最后的i,自然边界为偶数,而又有c2申请了4个只用了1个,3个够用,所以可以只后移一位,地址为10,结构体大小依旧为12。
再看最后一个例子:
struct TestStruct6
{
       char c1;
       int j;
       short i1;
       char c2;
       short i2;
};
    
    c1如果地址0,那么j为4,i1为8,char c2为10,接下来的地址为11,由于i2自然边界是偶数,则后移到12,这时i1申请的4个地址全部用完,这时i2申请的大小应该为多少呢,实验证明:还是申请4。结构体大小为:16。
    以上看来,结构体的设计技巧对内存空间的管理还是很重要的,
    而在C中允许干涉内存对齐的“家庭纠纷“的方法就是用预处理命令#pragma,在所有预处理命令中,它可能也是最复杂的,它的作用是设定编译器的状态或是指示编译器完成一些特定的动作,关于这个命令的用法,我还没详细了解多少。
    这里用到的是:#pragma pack(n) 和#pragma();前者是编译器按n个字节对齐,后者是取消编译器的自定义字节对齐方式,一般需要对一个对象自定义,则将其写在两者之间即可。

    #SinaEditor_Temp_FontName它的规则是:成员自身的对齐方式和n相比,字节对齐是以较小的为准。

    本文转载自关于内存对齐

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值