我是靠谱客的博主 幽默吐司,最近开发中收集的这篇文章主要介绍如何理解结构体链表的内部结构?,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

以下基于地址结构来理解几个要点,自记录并供您参考:

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;
}


最后

以上就是幽默吐司为你收集整理的如何理解结构体链表的内部结构?的全部内容,希望文章能够帮你解决如何理解结构体链表的内部结构?所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(45)

评论列表共有 0 条评论

立即
投稿
返回
顶部