结构体对齐(图解)与位域

来源:互联网 发布:python opencv 摄像头 编辑:程序博客网 时间:2024/06/06 13:25

一、结构体对齐

 在计算结构体大时往往需要考虑到结构体对齐,简单的总结下我的一些经验。
结构体对齐时,先找出本结构中最大类型的长度,先考虑自身对齐,最后考虑整个结构对齐(把最大类型长度看做模数来对齐,32位下模数最大为4),下面用图解法进行分析:

例:(64位系统,模数最大为8,所以结构体最大对齐值为8 ; 32位系统最大模数为4,结构体对齐值最大为4)

#include <stdio.h>struct A{    char a;    //1    int c;     //4    double b;  //8};struct B{    char a;     //1    double b;   //8    int c;      //4};void main(){    struct A x;    struct B y;    printf("%d,%d\n",sizeof(x),sizeof(y));}

64位输出结果:16 , 24
32位输出结果:16,16


对于64位系统:

解析:
这里写图片描述

首先,64位系统,最大类型为double长度为8,所以确定结构体对齐值为8。

1、对于结构体A:
  首先,放char a ,字节长度为1,然后放int b(长度为4),1+4 = 5 < 8 ,下一个要存放的是 double类型,所以不够了,另外存放一块为8的空间所以总大小为

5 +1 +3(填充部分)+8 = 16 。

2、对于结构体B:
  首先放char型 ,占 1 个位置;下一个要放的double占8个字节,不够放了,,所以填充7个字节。double找下一块空间放,刚好占满8。再存放int (4字节),最后占了20字节空间,然后需要与结构体对齐(模数为8),所以最后结果为24。

1(char) +7(填充部分)+8 (double)+4+4(模数对齐后填充部分) = 24


对于32系统

解析:
这里写图片描述

结构体A和B大小都为 16 。
每个数据对 模数4对齐,不够的话用两块单位为4的块来存,小于4 ,对4对齐,最后结构体总大小对4 对齐。
对于结构体A:

1(char)+3 (填充部分) + 4 (int) +8(double) = 16

对于结构体B

1 (char)+3(填充部分)+8(double) + 4 (int) = 16 (已对齐)


二、位域:

  位域是指信息在存储时,并不需要占用一个完整的字节, 而只需占几个或一个二进制位。例如在存放一个开关量时,只有0和1 两种状态, 用一位二进位即可。为了节省存储空间,并使处理简便,C语言又提供了一种数据结构,称为“位域”或“位段”。

记住:位域不能跨字节

例题1:int :0表示相面出现的类型不能够再往里面填充。

struct area{      int a:3;         int:0;     //告诉下面,20不能够放到a的那块存储区域去了      int c:20;};

所以该结构体大小为 4 + 4 = 8;如果没有 int : 0那一句,则大小为4.


例2: int : x 表示占用几个为,占用部分不可用,但是接下来的位可继续往上面填充。

struct area{      int a:3;         int:4;     //告诉下面,如果我们总大小没超过32,你可以继续填充a的区域      int c:20;};

所以该结构体大小为 4 。


例题3 位域不能跨字节,**位域需要跟结构体最长类型对齐,前面的类型应自动对齐,然后再进行填充。

struct area{      char a:6;   //向int对齐,扩展为32位      char b:3;      int c:20;};

结构体大小 :8


struct area  //64位,向double对齐 {      char a:6;      long b:63;      char c:3; };

结构体大小为:24


注意:short为2,作为模数,用于对齐位域是对最长的数据对齐,

struct area   //对short对齐,扩展为16位{    char a:2;    short b:10;    char c:3; };

结果为:2
如果把 3 改为7,结果就变为 4 了,因为最后c也需要对short对齐。