C语言:字节对齐、问题

来源:互联网 发布:mysql update 日期 编辑:程序博客网 时间:2024/05/20 06:06
 
     昨天在运行这样的代码的时候突然有问题了,话不多说,贴上简化后的代码:
      
#include <stdio.h>

struct X
{
   char   m_b;
    int     m_a;
   short   m_c;
}SX;

struct Y
{
   int     m_a;
   char   m_b;
   short  m_c;
}SY;

int main( int argc, char ** argv )
 
    printf("size、struct X == %d\n", sizeof(SX));
   
    printf("size、struct Y == %d\n", sizeof(SY));

    return0;
}

      大家先可以不运行,猜猜答案是什么,您猜对了吗?呵呵呵~
      看看我在gcc下的结果:
      pt@ubuntu:~/桌面/test$ ./test
      size、struct X == 12
      size、struct Y == 8

      大家可能会很奇怪是吧,一样的代码,一样的数据结构,为什么结果会不一样呢,呵呵呵,当时我也蒙了,最后没办法,google吧,最后才知道这是设计到“字节对齐 ”问题!

>>>>>:
     下面就看看什么是字节对齐:

      现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定类型变量的时候经常在特定的内存地址访问,这就需要各种类型数据按照一定的规则在空间上排列,而不是顺序的一个接一个的排放,这就是对齐。

     概念来自百度百科: http://baike.baidu.com/view/1523557.htm

    自己理解一下:我们知道,对于结构体或者是数组来说,对于里面的单一的元素都是通过对于首地址的偏移来处理的,但是计算机为了处理上面的更方便,还有一些特殊的内存地址等原因。例如一些平台对特定的数据只能从一些特定的地址开始存取,所以如果是跨平台的话,那么很大可能的结果就是降低了存取的效率问题,所以为了解决这些问题,就引入了“字节对齐”!

>>>>>:
     在我的的OS中,int是4字节,char是1字节,short是2字节,那么其实有效的字节数是7对吧,但是上面的结果却是12和8,为什么呢,呵呵呵~
     
     理解几个概念:
     <1>.内部元素自身对齐字节:例如int就是4这样的;
     <2>.内部元素的实际对齐字节:我们的OS有默认的对齐字节(我这里是4字节,当然可以自己改,后面再说)
     <3>.结构体的自身对齐字节:max( 每个元素自身对齐字节)
     
     先看看字节对齐算法的实现:
     对于结构的对齐而言,要分成两部分,
     一个是:内部单个元素的对齐;
     二个是:结构体整体的对齐;
 >>>:
     看一:
     要求是:  首地址 % 实际对齐字节 ==0,而且所有元素对自身的处理都是按照定义的顺序进行的哦!第一个元素的地址就是整体的首地址,所有的都是与第一个进行对齐,紧密摆放!  
    看二:
    要求是:  对于整体而言,整体的字节数也是字节长度必须是可以整除结构体的实际对齐字节数!

    话不多说,看看DEMO:
    structX
    {
       char   m_b;     //!> 1字节
       int     m_a;     //!> 4字节
      short   m_c;     //!> 2字节
    }SX;
   
   注意:在我的OS中,默认值是4字节对齐
  假如首地址是:0X0000,那么我们知道对于m_b的实际对齐字节数是min( 1, 4 ) == 1,所以有
   0X0000 % 1 ==0是可以的,所以m_b保存在0X0000中;对于m_a,可知实际对齐字节数是:min( 4,4 ) == 4,
   所以只能是 0X0004 % 4 ==0,所以前面的0X0001 -> 0X0003是没有实际使用的!所以m_a保存在
   0X0004 ->0X0007;最后对于m_c,可知实际对齐字节数:min( 2, 4 ) == 2, 所以可以是 0X0008 % 2 ==0,
   所以保存在0X0008 ->0X0009中
   至此:内部单一元素处理完成!!!
   
   对于整体而言,可以知道现在整体是10字节,又因为
   结构体的实际对齐字节数 = max( 4, max(每个元素的自身对齐字节数 ) ) == 4,
   又因为10 % 4 != 0,所以只能增加成12,:-)~,这就是为什么结果是12了,呵呵呵~
 
  对于第二个交换内部元素顺序后的处理,自己可以处理看看、、、

>>>>>:
   最后介绍一下自己改变系统默认对齐值的处理:
   #pragma pack( 2);   //!>按照自定字节2对齐
    structX
    {
       char   m_b;     //!> 1字节
       int     m_a;     //!> 4字节
      short   m_c;     //!> 2字节
    }SX;
    #pragmapack();   //!> 取消自定对齐,恢复默认。。。。

   可以自己尝试一下上面的代码结果是:8      

 
   呵呵呵,至此结束~

原创粉丝点击