跳转至

结构体是什么

基础补充 · 专题阅读 · 保留代码与校订注 · 本次导入快照

结构体是什么

很多同学背了 struct LNode { int data; struct LNode *next; };,但完全不懂这段代码在说什么。

int 变量是一堆钱,char 变量是一本书。如果我们想把某些物品打包装一起就需要使用 struct。

结构体就是定制一款包,刚好能装下这些东西(先不考虑对齐问题)。包中会有多个口袋,每个口袋装一个东西,比如说下面的爱马仕菜篮子(Picotin Lock 18)

结构体的"包"类比

代码拆解:

struct LNode                 // 1. 宣布:一款叫 struct LNode 的包
{
    int data;                // 2. 口袋1:放一堆钱(一个整数)
    struct LNode *next;      // 3. 口袋2:放一张纸条,记录了某个同款包的位置
};

如何使用这样的包呢,可以直接使用 LNode 吗?不行,首先得买一个包A,也就是:

struct LNode A;              // 定义一个变量A,也就是买了一款叫 struct LNode 的包
struct LNode *p;             // *p是一个包,而p是一个指向包的指针(纸条)

这个包里面有部分,分别是 data (int 钱) 和 next (struct LNode * 纸条)。要查找某部分需要使用 "包名字.data" 和 "包名字.next"。而如果我们手上只有纸条 p,就需要根据纸条的线索去查找,也就是使用 ->(有个查找和推测的过程)。所以大家在使用的时候一定要问自己一句:我拥有的的是什么?,区分A、p是结构体还是指针,结构体使用 .,指针使用 ->:

A.data = 10;
A.next = NULL;
p->data = 10;
p->next = NULL;

但是我们发现,每次定义(买包)都需要使用 struct LNode,比如这款包叫"人造的爱马仕菜篮子"太长太难听了,所以我们给他改个名字,叫 原神 爱马仕。用法:

typedef 原名称   别名1,别名2,…;
typedef struct LNode   LNode;        // 把 struct LNode 取别名 LNode

那如果把以下两条指令结合:

struct LNode                 // 1. 宣布:一款叫 struct LNode 的包
{
    int data;                // 2. 口袋1:放一堆钱(一个整数)
    struct LNode *next;      // 3. 口袋2:放一张纸条,记录了某个同款包的位置
};
typedef struct LNode   LNode;        // 把 struct LNode 取别名 LNode

就变成

typedef struct LNode         // 1. 宣布:一款叫 struct LNode 的包
{
    int data;                // 2. 口袋1:放一堆钱(一个整数)
    struct LNode *next;      // 3. 口袋2:放一张纸条,记录了某个同款包的位置
} LNode;

接下来就只需要这样定义了:

LNode A;                     // 定义一个变量A,也就是买了一款叫 struct LNode 的包
LNode *p,*q;                 // *p是一个包,而p是一个指向包的指针(纸条)

我还是觉得有点丑,每次定义指针都需要加一个 *,能不能优化一下,给一个指针类型(纸条也取名,一类指向这款包的纸条也有名字 linklist)

typedef struct LNode         // 1. 宣布:一款叫 struct LNode 的包
{
    int data;                // 2. 口袋1:放一堆钱(一个整数)
    struct LNode *next;      // 3. 口袋2:放一张纸条,记录了某个同款包的位置
} LNode, *linklist;

修改之后

LNode A;                     // 定义一个变量A,也就是买了一款叫 struct LNode 的包
linklist p,q;                // *p是一个包,而p是一个指向包的指针(纸条)