结构体内存对齐以及空间大小

一.结构体内存为什么要对齐?

1.移植原因 - 计算机在内存读取数据时,只能在规定的地址处读取数据,而不是内存中任意地址都是可以读取的。不是所有的硬件平台都能访问任意地址上的数据,某些硬件平台只能在某些特定的地址处取某些特定的数据:比如有的只能读取地址处地址为8的倍数或者4的倍数等的数据。

2.效率原因: - 正式因为第一条的原因,在访问一些数据时,对于访问了为对齐的内存,处理器需要2次访问,而对齐的内存只需要一次。为什么不对齐的话要2次呢? 比如结构体中的2个成员char i = 'a'; int j = 100;  i占一个字节,int占4个字节, 比如32为的系统读取的时候一次要读4个字节,读取i相当于也读取了j的前3个字节  再去读取j的时候也要先读取i的后3个字节再去读取j。

当结构体内存对齐之后就变成了这样:  这里只是一种情况,其他的要参考结构体所占大小的规则。

再去读取的时候就能一次读取了。

二.结构体所占空间大小

结构体的大小不是所有成员大小简单的相加,需要考虑到系统在存储结构体变量时的地址对齐问题。

注:后面代码都是在windows下vs中执行

计算规则:    

1.结构体的第一个成员的地址就是结构体变量偏移量为0的地址处,可以看做是这个结构体内存的头

2.除了第一个的其他成员需要对齐某个数字的整数倍的地址处。这里的某个数字(也可以叫对齐数)为编译器默认的对齐数与该成员的大小比较取最小值。编译器默认的对齐数可以用#pragma pack(show)查询,也可以#pragma pack (N) 修改,N即为修改的值,这个值只能是1,2,4,8,16。注意: 不同的编译器/操作系统对用的默认对齐数可能会有不同,vs中默认是8,Linux默认为4。 成员占的大小为自己所占的大小

3.结构体的总大小要为结构体中最大对齐数的整数倍

 

例1:

struct stu1

  {

  int i;

  char c;

  double j;

        char a;

  };

printf_s("sizeof( stu1):%d\n", sizeof(struct stu1));  //结果为24

先介绍一个相关的概念——偏移量。偏移量指的是结构体变量中成员的地址和结构体变量地址 的差。结构体大小等于最后一个成员的偏移量加上最后一个成员的大小。显然,结构体变量中第一个成员的地址就是结构体变量的首地址。因此,第一个成员i的偏 移量为0。第二个成员c的偏移量是第一个成员的偏移量加上第一个成员的大小(0+4),其值为4;第三个成员j的偏移量是第二个成员的偏移量加上第二个成 员的大小(4+1),其值为5,因为有了地址对齐的要求,编译器在编译程序时会遵循上面3个规则:

        对照第1条,结构体第一个成员偏 移量为0,所占大小为4字节

  对照第2条,上面的例子中前两个成员的偏移量都满足要求,但第三个成员需要对齐8(vs默认对齐数为8,8和4比较取最小值)的整数倍的地址处,但在这里是5的位置,编译器在处理时会在第二个成员后面补上3个空字节,使得第三个成员的偏移量变成8。

  对照第3条,结构体总大小要为结构体中最大对齐数的整数倍。也就是8的整数倍,从上面加起来为4+4+8+1 = 17 ,3*8 = 24才能存下这个结构体,所以例子中计算出来的大小为24

例2:

struct A {
    char c0;    //1
    char c1;    //1
    char c2;    //1
    char c;        //5
    double d;    //8
    int i;        //4
    int j;        //4
    char c3;    //1            32
};

printf_s("sizeof(A):%d\n", sizeof(struct A)); //结果为32

如果是嵌套结构体,最方便的就是各算各的然后加起来。

 

注: 以上仅作为本人学习后的总结。

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值