关于 sizeof (结构体)

编译器默认会对结构体进行处理(实际上其它地方的数据变量也是如此),让宽度为2的基本数据类型(short等)都位于能被2整除的地址上,让宽度为4的基本数据类型(int等)都位于能被4整除的地址上,以此类推.这样,两个数中间就可能需要加入填充字节,所以结构体的sizeof值就不是简单的成员的sizeof相加了.
   
   字节对齐的细节和编译器实现相关,一般满足以下三个准则:
1) 结构体变量的首地址能够被其最宽基本类型成员的大小所整除;
2) 结构体每个成员相对于结构体首地址的偏移量(offset)都是成员大小的整数倍,如有需要编译器会在成员之间加上填充字节(internal adding);
3) 记住:结构体的总大小为结构体最宽基本类型成员大小的整数倍,如有需要编译器会在最末一个成员之后加上填充字节(trailing padding).


说明:
(1)这里所说的“数据宽度”就是指其sizeof的大小.由于结构体的成员可以是复合类型,比如另外一个结构体,所以在寻找最宽基本类型成员时,应当包括复合类型成员的子成员,而不是把复合成员看成是一个整体.但在确定复合类型成员的偏移位置时则是将复合类型作为整体看待.
(2)有一个影响sizeof的重要参量还未被提及,那便是编译器的pack指令.它是用来调整结构体对齐方式的,不同编译器名称和用法略有不同,VC6中通过#pragma pack实现,也可以直接修改/Zp编译开关.#pragma pack的基本用法为: #pragma pack( n ),n为字节对齐数,其取值为1、2、4、8、16,默认是8,如果这个值比结构体成员的sizeof值小,那么该成员的偏移量应该以此值为准.
(3)“空结构体”(不含数据成员)的大小不为0,而是1.




例1:
#include "stdio.h"
void main()
{
    
    struct list
    {
              int a;   //4个字节
              char b[5]; //占5个+3个空字节=8字节       
    }s[3];
    char c[5];
    printf("%d\t\t\t%d\t\t\t%d\n",sizeof(int),sizeof(c),sizeof(struct list));
}

输出:  4      5      12


解释:

32位对齐,也就是4个字节
    struct list
    {
              int a;             /4个字节
              char b[5];     /占8字节

    }s[3];


例2:

#include "stdio.h"
void main()
{
  struct time
 {
  int year;  //4
  short month;//2
  short day;//2
  short hour;//2
  short minute;//2
  short second;//2
  };

  struct Battery 
 {
  short list; //2
  int Integer; //4
  int Deci;    //4
  struct time date;  //当前时间
 };


printf("%d\t\t\t%d\n",sizeof(time),sizeof(Battery));
}


输出:

16                            28

解释:

在struct time中,字节数总和是14,根据上述第三个准测实际大小是最大成员的整数倍,所以4*4=16>14。所以输出字节是14+2个填充字节。struct Battery中struct time date是根据说明1中要求,把struct time date看成整体16字节,16+2+4+4=26,在计算struct Battery 大小时,要看struct time date中的子成员与struct Battery 的3个子成员中最大字节数的整数倍。所以是4*7=28>26。所以struct Battery 的大小为28(最后2位为填充字节)。


例3:

#include "stdio.h"
void main()
{
  struct time
 {
  int year;  //4
  short month;//2
  short day;//2
  short hour;//2
  short minute;//2
  short second;//2
  };

#pragma pack(1)  //表示1字节对齐
  struct Battery //注意 字节对齐问题 4个字节(32位)内存同一分配
 {
  short list; //2
  int Integer; //4
  int Deci;    //4
  struct time date;  //当前存储时间
 };
#pragma pack()  //取消对齐

printf("%d\t\t\t%d\n",sizeof(time),sizeof(Battery));
}

输出:

16           26


解释:

#pragma pack(1)  //表示1字节对齐---根据上述说明2。当取1字节对齐后无需加入填充字节,所以最后struct Battery 的大小为16+2+4+4=26.


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值