概述
以下基于地址结构来理解几个要点,自记录并供您参考:
1、迭代运算时,为什么临时变量必须是指针型标签?
- 查看 结构体指针域的 *next 的内存地址结构如下:
0x003ffb30 {name=0x002e6b40 "33" next=0x00000000 <NULL> }
所以,为便于传递,临时标签必须与 *next相同结构,同样是指针型。
2、 如何理解 求值符*与求地址符& ?
查看 *next 的地址结构如下:
next 0x003ffb40 {name=0x002e6b38 "22" next=0x003ffb30 {name=0x002e6b40 "33" next=0x00000000 <NULL> } } student *
查看 *next所指结点 的地址结构如下:
s2 {name=0x002e6b38 "22" next=0x003ffb30 {name=0x002e6b40 "33" next=0x00000000 <NULL> } } student
可以看出,s1.next 就是在 s2 地址上增加了一层新地址,该新地址就是 “s1.next” 标签所在地址, “s1.next” 的值就是 s2 。
简述为:
- 定义指针型标签是增加一层地址;
- 求值符 * 是剥去一层地址;
- 求地址& 是求标签的地址;
3、示例代码如下,有详细的地址结构说明:
| //第一 node
|+ s1 {name=0x002e6b30 "11" next=0x003ffb40 {name=0x002e6b38 "22" next=0x003ffb30 {name=0x002e6b40 "33" next=...} } } student
| name 0x002e6b30 "11" char *
| 49 '1' char
| next 0x003ffb40 {name=0x002e6b38 "22" next=0x003ffb30 {name=0x002e6b40 "33" next=0x00000000 <NULL> } } student *
| name 0x002e6b38 "22" char *
| 50 '2' char
| next 0x003ffb30 {name=0x002e6b40 "33" next=0x00000000 <NULL> } student *
| name 0x002e6b40 "33" char *
| 51 '3' char
| next 0x00000000 <NULL> student *
| name <无法读取内存>
| next <无法读取内存>
|
| //第二 node
|+ s2 {name=0x002e6b38 "22" next=0x003ffb30 {name=0x002e6b40 "33" next=0x00000000 <NULL> } } student
|
|
| //临时标签 head 与 next相同地址结构
|+ p 0x003ffb50 {name=0x002e6b30 "11" next=0x003ffb40 {name=0x002e6b38 "22" next=0x003ffb30 {name=0x002e6b40 "33" ...} } } student *
全部代码如下:
// struct_linklist_3.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
// 声明结构体
struct student
{
char * name;
struct student * next;
};
// 分析 结构体 链表的地址层次:
/*
| //第一 node
|+ s1 {name=0x002e6b30 "11" next=0x003ffb40 {name=0x002e6b38 "22" next=0x003ffb30 {name=0x002e6b40 "33" next=...} } } student
| name 0x002e6b30 "11" char *
| 49 '1' char
| next 0x003ffb40 {name=0x002e6b38 "22" next=0x003ffb30 {name=0x002e6b40 "33" next=0x00000000 <NULL> } } student *
| name 0x002e6b38 "22" char *
| 50 '2' char
| next 0x003ffb30 {name=0x002e6b40 "33" next=0x00000000 <NULL> } student *
| name 0x002e6b40 "33" char *
| 51 '3' char
| next 0x00000000 <NULL> student *
| name <无法读取内存>
| next <无法读取内存>
|
| //第二 node
|+ s2 {name=0x002e6b38 "22" next=0x003ffb30 {name=0x002e6b40 "33" next=0x00000000 <NULL> } } student
|
|
| //临时标签 head 与 next相同地址结构
|+ p 0x003ffb50 {name=0x002e6b30 "11" next=0x003ffb40 {name=0x002e6b38 "22" next=0x003ffb30 {name=0x002e6b40 "33" ...} } } student *
|
|
| 结构体 运算符:
| “->” :当结构体标签为 指针(即相对于下层标签 为 2 层地址时),求结点内成员的值;
| “.” :当结构体标签不是指针(即相对于下层标签 非 2 层地址时),求结点内成员的值;
|
|
| 结构体 链表的 临时指针
| 循环时必须使用指针,使地址结构与 next相同,结构如下:
| next 0x003ffb30 {name=0x002e6b40 "33" next=0x00000000 <NULL> } student *
| 解释: 标签: 0x003ffb30 { &node: name=0x002e6b40 "33" next=0x00000000 <NULL> }
| 例: struct student *p = &s1;
|
|
| 结构体的
| 标签 label : 如 name=0x002e6b30 "11",看似 使用首个成员的 name 标签,实际不能通过 *label 求出首成员的值。
| 地址 address: 如 0x002e6b30,使用首元素的地址,与数组相同;
| 值 : 各不相同
| 所以,结构体的标签 无特殊用处。
|
*/
void linklist_1()
{
//组成单链表
struct student s1 = { "11", NULL }; // s1地址是“ 11”的地址即 '1'地址。根据单向原则,不能从该地址取值 1,只能代表整个结点
struct student s2 = { "22", NULL };
struct student s3 = { "33", NULL };
s1.next = &s2;
s2.next = &s3;
//声明临时指针,也是头指针。
struct student *p = &s1;
while (true)
{
if (p->next != NULL)
{
printf_s("%sn", p->name);
p = p->next;
// 循环时,必须使用指针型的临时变量 p,使得 p 的结构与 next 的结构相同,切记!所以 必须定义为 struct student *p = p->next
// 地址结构为: next 0x003ffb30 {name=0x002e6b40 "33" next=0x00000000 <NULL> } student *
}
else
{
printf_s("%sn", p->name);
break;
}
}
};
int main()
{
linklist_1();
return 0;
}
最后
以上就是幽默吐司为你收集整理的如何理解结构体链表的内部结构?的全部内容,希望文章能够帮你解决如何理解结构体链表的内部结构?所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复