结构体对齐 字节计算(通俗易懂)

结构体对齐 字节计算(通俗易懂)

结构体对齐的作用意义:

为了cpu高效的去取内存上的数据

解释:
地址总线
地址总线:找到内存中的数据地址 数据总线:每次取数据取多少
如图:char a这个数据占一个字节,在4这个位置,如果后面b这个数据紧跟在a后面,则b占的地址为5-9共4个字节,在32位机器中数据总线一次访问4个,那么我们按照地址访问则只能按照4的整数倍,0,4,8…这样去找数据,所以拿到b这个数据就要找两次,并不高效,所以将数据对齐,便很有必要。

对齐的规则

一、结构体对齐规则首先要看有没有用#pragma pack宏声明,这个宏可以改变对齐规则,有宏定义的情况下结构体的自身宽度就是宏上规定的数值大小,所有内存都按照这个宽度去布局(这样说其实不太严谨,后面会提到),#pragma pack 参数只能是 ‘1’, ‘2’, ‘4’, ‘8’, or ‘16’。

二、在没有#pragma pack这个宏的声明下,遵循下面三个原则:

1、第一个成员的首地址为0.

2、每个成员的首地址是自身大小的整数倍

3、结构体的总大小,为其成员中所含最大类型的整数倍。

下面我们以32位机器为例,通过几个例子来详细说明。

struct test
{
  char a;  //1
  char b;  //1
  char c;  //1
};

这个结构体占几个字节呢?答案是3个。你可能觉得很简单,每个变量都是占一个字节,三个当然加起来就是3了。
那如果把第二个变量改成short呢?

struct test
{
  char a;  //1
  short b;  //2
  char c;  //1
};

如果你觉得是4个,那就错了。答案是6个。

来结合对齐规则来看一下,1、第一个成员首地址为0(准确说是偏移量),这个没什么好说,2、每个成员的首地址是自身大小的整数倍,因为b是short类型的,占用两个字节,所以,必须以2字节对齐,也就是说你可以把b放在0啊,2啊,4啊这些地址,但是你不能放在1,3,5这样的地址。a的地址是0,下一个地址是1,不能放,只能空掉,放在2位置处。这样,a和b就占了4个字节了,接下来c占一个字节。但是,还没完,看第三条规则,结构体的总大小,为其成员中所含最大类型的整数倍。所以,在这个例子中,结构体总大小应该要为2的整数倍,所以是6,而不是5。
图示:
在这里插入图片描述
再看这个,分析和前面是一样的,答案是12.

struct test
{
  char a;   //1+3
  int  b;    //4
  short c;    //2+2
};

在这里插入图片描述
再看这个:

struct test
{
  char d[7]; //地址0:7+1
  double a;//8:8
  short  b;//地址16:2+2
  char* c;//地址:20:4
};

这个答案是24,这里只要注意数组分析是一样的,7个应该要补成8个字节,还有就是最后所有的指针在32位系统中都是占4个字节。
前面讲的都是没有用#pragma pack 这个宏声明的情况,接下来分析一下如果有这个宏声明有什么不同。

#pragma  pack(1)
struct test
{
  char a;
  int  b;
};

根据我们之前的分析,这个结构体应该要占用8个字节,但是因为加了#pragma pack(1)
导致整个结构体按照1字节来对齐,所以结果是5,不再是8.
在这里插入图片描述
如果是#pragma pack(2)呢?相信大家都能想到答案是6.
在这里插入图片描述
!!!注意一点:并不是所有的宏声明都是有效的,是按照这个宏声明的和实际数据类型中最大值较小的那个来决定。
例:

#pragma  pack(8)
struct test
{
  char a;
  int  b;//4
  short c;
};

这里数据类型最大为int 占4个字节,比8小,所以按照4个字节对齐,而并不是8,因此结构体大小为12。因此在判断时候,需要比较最大类型与宏声明的大小,决定按多少对齐。

ps:理解不是特别深刻,如有相关知识点错误还请谅解指出,谢谢。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

叼馋爱偷猪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值