C语言:结构体内存对齐

前言:本人为C语言初学者,学识尚浅,研究程度存在很大的局限性,眼界很窄。以下所有观点仅代表个人见解和思路,各位游刃有余的前辈可以给予批评和指正!各位与鄙人同路的学子可相互探讨、发表看法,交换观点!

如果你学习了结构体,那么应该不至于对它太陌生:

struct tag
{
    member - list;
};

int main()
{
    struct tag s = {0};    

    return 0;
}

但是结构体在内存中占多大空间呢?

例如:

struct test
{
    char a;
    int b;
    double c;
};

如果按照我们的正常思维,它所占的空间应该是:1(char)+ 4(int)+ 8(double) = 13byte

但事实是否就如我们所想的呢?我们不妨用 sizeof 来计算一下大小:

struct test s = {0};
printf(“%d\n”, sizeof(s));

 而答案却不如我们所料,这到底是为什么呢?

所以进入我们今天要讨论的话题:结构体内存对齐

首先,我把4条规则先罗列于此,然后分析:

1.第一个成员在结构体变量偏移量为0的地址处

2.其他成员变量要对其到对其数的整数倍的偏移量地址处

(对齐数:编译器默认的一个对齐数与该成员大小的较小值,VS默认为8)

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

4.如果结构体中嵌套了结构体,则嵌套的结构体对齐到自己结构体中最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。

struct test
{
    char a;
    int b;
    double c;
};

就这一串而言,我们先凭借前三条分析为何为16byte。

 这是我们的内存段,依据第一条规定,char 类型直接存储在偏移量为0的位置,即如下:

接下来是int类型,依据第二条规定,我们首先要找到对齐数:int类型为4,VS默认为8,4和8中取一个较小值,即为4。所以int的起始位置应该是偏移量为4的倍数的地方,即偏移量为4的地方: 

 接下来是 double 类型,还是要找到对齐数,因为其大小都是8,所以对齐数也就是8,而从偏移量为8的倍数开始,刚好就是 int 下面的一块空间,即存放如下:

而至于第三步,现在整个结构体所占空间是 16byte(0~15),刚刚我们获得的对齐数有 int 的4和double 的8,所以取最大数是8,而 16byte 刚好又是8的整数倍,所以这里16即为最终结果。

当然,这里或许第三条规定不能很好体现,如果我们把结构体的 double 修改成 char :

struct test
{
    char a;
    int b;
    char c;
};

前两步同理,而第三步时,我们的 char 类型为1,VS默认为8,所以取较小值为1,即其实 char 什么位置都可以放,因为不管哪个数都是1的倍数:

这里整个结构体所占空间为9,但是在所有对齐数中最大的是 int 的4,9不是4的倍数,所以结构体只能在11的位置真正的结束,营造出 12byte 的空间。

 以下用绿色标记的空间是未使用的,换句话说,浪费了:

 既然这样,前三条规定我想大家已经有了清楚的认知,那么对于第四条规定,我们还得举例说明:

struct test1
{
    char a;
    int b;
    char c;
};

struct test2
{
    int i;
    struct test1 s1;
    char ch;
};

int main()
{
    struct test2 s2 = {0};

    printf("%d\n", sizeof(s2));

    return 0;
}

1.放 int 类型:

2.放结构体类型:

此结构体s1已在上文中详细解析,其所占空间为12。而在结构体test1中,其最大对齐数是4,所以结构体要放在偏移量为4的整数倍的位置,刚好int类型放完下一位就是4,所以是这样放的:

 

3.放 char 类型,char 类型的对齐数肯定是1,所以往后放就OK了: 

当然,最后一步是计算整个结构体空间的大小,但这时我们的结构体大小为 17byte(0~16),而在所有的对齐数中,int 为4,struct test1 为4(取这一结构体中最大对齐数),char 为1,所以取所有值的最大值,也是4,但是17不是4的整数倍,只能到20byte才行,所以这个结构体最后结束在19,如下: 

 

END

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Thepale2022

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

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

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

打赏作者

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

抵扣说明:

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

余额充值