文章目录
前言
一、结构体类型的声明
1、结构体的基础知识
2、结构体的声明
3、特殊声明
二、结构体的自引用
三、结构体变量的定义和初始化
1、结构体的定义分为两类
2、结构体的初始化
四、结构体内存对齐
1、结构体在内存中是怎样存放的呢?
2、结构体的对齐规则:
3、为什么存在内存对齐?
4、注意
5、修改默认对齐数
五、结构体传参
六、结构体位段的实现
1、什么是位段
2、位段的大小
3、位段的内存分配
4、位段不跨平台的原因
总结
前言
路漫漫其修远兮,吾将上下而求索;
一、结构体类型的声明
1、结构体的基础知识
结构体是一些成员变量的集合,每个成员可以是不同类型的变量;
2、结构体的声明
可以在创建结构体类型的时候同时捎带着创建结构体变量,也可以在有了结构体类型之后再创建结构体变量;
3、特殊声明
在声明的时候,可以不完全声明;
例如:匿名结构体类型(即无结构体标签 tag)
在匿名结构体中,即使有两个成员变量的类型、大小都一样的结构体类型,只要该结构体变量不是在同一个匿名结构体创建的变量,编译器会认为它们的类型不同;例子如下图:
二、结构体的自引用
在结构中包含一个类型为该结构本身的成员是否可以呢?
例子如下:
以上例子是不可行的,因为将struct Node 作为类型定义的成员又作为结构体类型struct Node 的成员,就好比”先有鸡还是先有蛋“的问题,是个无厘头问题;
在讲述结构的自引用之前,我们先来了解一下一些相关的基础知识;
如果你想在内存中存放数据 1 2 3 4 5,想让其像数组一样在内存中连续存放,这便是顺序表;即顺序表这种结构中的数据在内存中连续存放;
那如果数据不在内存中连续存放呢?
如上图所示,如果你找到了1,1可以找到2,2可以找到3,3可以找到4,4可以找到5,即找到1后面的数字就都可以找到了;这种方法就像一个链条,将这些数据串起来了,故而叫做链表;
那么如何实现链表呢?
你可能会这样想,在1的位置包含1的数值和2的结点,1便可以找到2;在2的位置包好2的数值和3的结点,2便可以找到3;在3的位置包含3的数值和4的结点,3便可以找到4;在4的位置上包含4的数值和5的结点,4便可以找到5;
那么这个结点该如何设计呢?
呈现出来就是上图这个样子,无法利用sizeof(struct Node) 的大小,因为结构体类型中包含用结构体类型创建的变量的这种写法本身就存在问题;
所以就有人想到,让上一个结点包含下一个结点的地址;
写作以下方式:
struct Node
{
int date;
struct Node* next;
};
在结构体类型 struct Node中包含的结构体指针next 能找到自己同类型的一个结点,故而叫作自引用;
匿名结构体是否可以自引用?显然也是可以的。
请判断以下代码是否正确?
typedef struct
{
int date;
Node* next;
}Node;
答案:此代码是错误的。因为首先匿名结构体类型首先要存在,才能对此类型进行类型重命名,而其成员Node* next ; 中的类型不存在;--> 在创建结构体类