【C语言】结构体自己引用、结构体内存、结构体对齐规则。

时间:2023-02-20 11:23:51

????write in front????   

????大家好,我是謓泽,希望你看完之后,能对你有所帮助,不足请指正!共同学习交流????

????2021年度博客之星物联网与嵌入式开发TOP5~2021博客之星TOP100~2022博客之星TOP63~作者周榜84﹣作者总榜704~阿里云专家博主 & 阿里云星级博主~掘金优秀创作者⇿InfoQ创作者⇿51CTO红人⇿全网访问量50w+????

????本文由 謓泽 原创 如需转载还请通知⚠

????个人主页-​謓泽51Ctop的博客​????

????欢迎各位→点赞???? + 收藏⭐️ + 留言????

????系列专栏-​謓泽51Ctop的博客_【C语言】从0~1_51CTO博客​????
✉️我们并非登上我们所选择的舞台,演出并非我们所选择的剧本????

【C语言】结构体自己引用、结构体内存、结构体对齐规则。

 结构体自己引用 

结构体自己引用其实就是:结构体里面是可以包含结构体的。

struct Book
{
int id;
struct Book book;
}

【C语言】结构体自己引用、结构体内存、结构体对齐规则。

在上述代码中创建了一个结构体,在里面当中也创建了一个结构体。 

上述代码是错误的,因为它死递归了,没有限制大小,它的大小会一直增加下去,取决于你创建的结构体。

那么结构体该如何实现自引用。 如下代码所示↓

struct Book
{
int id;
struct Book* book;//指针变量大小固定可算
}

【C语言】结构体自己引用、结构体内存、结构体对齐规则。

上述代码才是自引用使用正确的, 自引用不是包含同类型的结构体变量,而是包含同类型的结构体指针。看到这个如果学过数据类型的小伙伴们可以快速的理解。

【C语言】结构体自己引用、结构体内存、结构体对齐规则。

数据域:存放的是我所要存储的数据。

指针域:是为了找到下一个的节点的地址。


结构体内存 

sizeof(表达式)→获取某个数据类型所占用空间的 字节数 或者 是表达式的长度。

那么我们来看看结构体内存的大小是多少,如下代码所示↓

#include<stdio.h>
struct B1
{
int name;
char c;
};
struct B2
{
char c1;
struct B1
char c2;
};
int main(void)
{
struct B1 s1 = { 0 };
printf("s1:%d\n", sizeof(s1));
struct B2 s2 = { 0 };
printf("s2:%d\n", sizeof(s2));

return 0;
}

【C语言】结构体自己引用、结构体内存、结构体对齐规则。

运行结果↓

s1:8

s2:12

这个时候张三就可能会有疑问了,说结构体B1不应该是5个字节吗,而B2应该是9个字节才对啊。 为什么会是这个样子阿~

这个实际上就是结构体内存对齐的问题了,让我们来看看这到底是为什么。

从上面我们知道结构体存储跟我们实际想象????的是不一样的,这里其实是在结构体的内存对齐当中是有结构体自己的规则的。

结构体对齐规则

我们以上述结构体类型B为示例。下面来说说结构体内存对齐的规则。

  1. 结构体的第一个成员放在结构体变量的内存中存储位置的0偏移出开始。
  2. 从第二个成员往后的所有成员,都放在一个对齐数(成员的大小和默认对齐数的较小值在这里int为4)的整数倍的地址处。
  3. 结构体的总大小是结构体的所有成员的对齐数种最大的那个对齐数的整数倍。
  • vs默认的对齐数为8,linux平台上无(没有对齐数的概念)。

如图表示↓

【C语言】结构体自己引用、结构体内存、结构体对齐规则。

所以这里的结构体内存占了12个字节,如果上面这个多去理解下,还是能够很容易理解的||ヽ(* ̄▽ ̄*)ノミ|Ю 

当然如果有嵌套情况,像下面代码一样。 

#include<stdio.h>
struct B1
{
double pai;
char c;
};
struct B2
{
char c1;
struct B1;
char c2;
};
int main(void)
{
struct B2 s = { 0 };
printf("%d", sizeof(s));
return 0;
}

运行结果↓

32 

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