关于 内存对齐 && sizeof 的介绍 2 —— 结构体(改)

内存对齐方式的原则 :

 

    1. 成员的对齐是按声明顺序进行的;(这个很重要)==》见例1

    2:在VC环境下的默认对齐值为8,PS:因为最大的非自定义类型对齐值为8。(对吗?)

    3:由于对齐是按照声明顺序进行对齐的,所以这就里就会出现一些对当前成员对齐方式的影响因素:

          为了方便理解,我们这边设定几个变量

          A:val_self(成员自身的对齐值 如int型为4) 

          B:val_total(编译指示对齐值(可通过#pragma pack 进行指定,若无强制规定,则默认为8)和最大结构体成员对齐值中较小值;)         

          影响因素1:首先,第一个声明的成员对齐值取val_total进行对齐;

          影响因素2:(若非第一个声明的成员)看前一个声明的成员内存对齐之后的状况:

                                 case1:若果上一个成员对齐后,所分配给其的空间剩余,且该剩余空间满足如下条件:

                                                条件1: 该剩余空间中存在偏移值为当前成员val_self的整数倍的字节块。

                                                条件2:  而且从该偏移算起,加上val_self仍不超出剩余空间的大小。

                                                则当前成员填充到从该偏移算起的内存中。

                                 例:

                                

  1.               struct test   //val_self 为1; val_total为8  
  2.   
  3.               {  
  4.                char cA; //首先按照val_total来分配内存,char占一个,剩余7个  
  5.                int iB;//上一个成员分配的空间剩余,且有偏移量为4的空间,而且4+4(int的val_self)==8,没有超过剩余空间,于是iB就填充到从偏移量为4开始的连续4个空间中。  
  6.                double dC;//  
  7.               };                     

                                 

                                case2:如果上一个成员内存分配后没有剩余空间,或者可以填充的起始偏移值加上自身的val_self超过了剩余空间大小,则当前成员仍按照val_total来分配内存。

                                接上例:


  1. struct test //val_self 为1; val_total为8  
  2.   
  3.  {  
  4.   char cA; //首先按照val_total来分配内存,char占一个,剩余7个  
  5.   int iB;//上一个成员分配的空间剩余,且有偏移量为4的空间,而且4+4(int的val_self)==8,没有超过剩余空间,于是iB就填充到从偏移量为4开始的连续4个空间中。  
  6.   double dC;//<span style="color:#3333ff;">因为上一个成员iB分配完后没有剩余空间,所以自己按照val_total来分配8个空间。</span>  

  1. };         

 

综上,struct test的size为:8(1 + 3(空出来) + 4) + 8 == 16
 

********************************************************

例1:声明顺序的重要性

 struct sample5
{
    char a;      ///1

    double b;  ///8

    char c;         ///4

    int d;      ///1

    char e;

};   32==》 8 + 8 + 8(1 + 3(空) + 4) + 8

 

 struct sample5
{
     double c;  ///8

     char a;      ///1

     char b;         ///4

     int d;      ///1

     char f;          


};   24 ==》8 + 8(1 + 1 + 2(空) + 4 ) + 8

 

以上的测试都是在VC环境下。


新加内容:(我认为这种理解更准确,摘自野火每日一题)

为了提高 CPU 的存储速度,编译器会对一些变量的起始地址做了“对齐”处理。
对齐方式(变量存放的起始地址相对于结构的起始地址的偏移量)  
char       偏移量必须为 sizeof(char)   即 1 的倍数  
int         偏移量必须为 sizeof(int)     即 4 的倍数    (跟编译器有关,有可能是 2)
float    偏移量必须为 sizeof(float)  即 4 的倍数  
double   偏移量必须为 sizeof(double)  即 8 的倍数  
short   偏移量必须为 sizeof(short)  即 2 的倍数

为了确保结构的大小为结构的字节边界数(即该结构中占用最大空间的类型所占用的字节数)的倍数,所以在为最后一个成员变量申请空间后,还会根据需要自动填充空缺的字节。

例一的解析为:

struct sample5
{
    char a;      ///1

    double b;  ///8

    char c;         ///4

    int d;      ///1

    char e;

};

1+7(空)+8+1+3(空)+4+1=25  由于最大类型为double型 所以结构体所占空间为8的倍数 需要填充7个字节 结果为32=1+7(空)+8+1+3(空)+4+1+7(空)

struct sample5
{
     double c;  ///8

     char a;      ///1

     char b;         ///4

     int d;      ///1

     char f;          


};  

8+1+1+2(空)+4+1=17  同样需要补充7个空字节  结果为24=8+1+1+2(空)+4+1+7(空)



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值