Struct字节对齐分析

原文:http://rohna.w.blog.163.com/blog/static/14574165200742110405575/     


在编程中,我们常常会碰到字节对齐这方面的问题,偶就曾经碰到过。公司要求我把一段在Linux下的源代码改为运行在Windows下,偶修正了所有的语法错误,可是出来的数据总是多出几个字节,一样的代码,为什么会多出几个字节???最后查看了其头结构,才知道罪魁祸首是字节对齐方式和Linux的不一样,在Linux下其是按2字节对齐,可是在VC++下默认是按8字节对齐,知道这,然后改正,果然一切OK!

       字节对齐在编程中是最容易被忽略而又很难查找的问题,为什么需要字节对齐???这要从数据在内存中的存放说起,在内存中,数据的存放是有一定限制和规定的,比如double基本数据在内存的地址是8的倍数,这样做有什么好处,我想最大的好处应该是存取效率。试想,如果CPU每次可以取出8字节的数据,那么存取double类型的数据只需要访问一次内存就可以完成,但是如果对齐方式不是8,那么如果恰巧数据是横跨在两个符合对齐要求的8字节内存快上,这就需要访问内存两次。当然,现在Intel CPU可以处理任何对齐方式的数据,但有些类型的CPU在碰到没有对齐的数据时将会出错!

       那么怎样来计算Struct结构的大小呢???以VC++6.0为例,采用默认设置,看看下面的结构,其Size是多少???
       struct tagTest01
       {
             char   chOne;
             short  shOne;
             int    iOne;
        };

       首先,chOne的基本数据类型为char,Size为1,占用1字节;shOne的基本数据类型为short,Size为2字节,所以其地址应该从2的整数倍开始,因此前面填充一个字节,这样它的偏移地址为2而不是1;iOne的基本数据类型为int,Size为4,而这里的偏移地址恰巧也是4,不用填充。因为已经是4的整数倍。好了,现在应该很明确,此结构的Size应为8。

       然后,我们把上述结构中的数据成员的顺序调换一下,再看看如下的结构它的Size是否有变化:
       struct tagTest02
       {
             int    iOne;
             short  shOne;
             char   chOne;
        };

       可能按照上面的分析,我们会理所当然地认为上述结构的Size为7,如果真是这样的话,如果把此结构当着一个数组的一个元素的,他们也应该是要按所要求的字节对齐方式对齐的,好了,这里问题就出现了,如果定义了这样的数组struct tagTest02 arrOne[10];arrOne[0]的首地址为0,那么arrOne[1]的地址是多少呢,7 ???这显然已经不是我们默认设置的8字节对齐方式了,所以在chOne后面还是要填充一个字节,这样才满足8字节的对齐要求。到这里应该明白了吧。

        好了,上面采用的是默认的8字节对齐方式,如果是1,2,4呢,我们怎样来计算其Size呢,这里本人经过实际的经验总结这几条规则:

        假设你要对齐的字节数为N,基本数据类型的Size为S,那么当S小于等于N时,采用S对齐方式来对齐,如果S大于N时则采用N来对齐,比如N为2,那么对于int型的数据其对齐方式还是2字节而不是4了,知道了这一点,我们就很容易计算出任何一个struct的size了。

        如果有兴趣的可以计算一下下面的结构的Size是多少(对齐方式N分别为1,2,4,8)?

       #pragma pack(N)       
       struct tagTest
       {
           short   shTest;
           char chOne;
           int  iTest;
           char chTow;
           double  dTest;
       };
       #pragma pack()

       注意:当N不是2的倍数的时候,将采用默认设置的字节对齐方式。

       以上是偶的一些个人见解,如果有错漏之处,望各位指正,谢谢!

       EMail:Rohna.w@163.com,欢迎交流!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值