初学数据结构,请教一个单链表的问题

adugmin 2010-03-23 11:43:30
一直无法静下心来学习数据结构,总是觉得太难呵呵,今晚,决定认真地学习他,学好他,就看了链表,就难住了。
我看到它初始化链表的函数是这样写的:

void InitList(struct sNode **HL)
{
*HL=NULL;
}

我看到形参就愣了,初始化链表,不就是将表头指针置为空指针吗?为什么要用二级指针,直接将表头指针置空不就行了吗?如:

void InitList(struct sNode *HL)
{
HL=NULL;
}
这就是我的疑问。
但我想,他这样写,应该是有他的意思,应该不会是作者的错或者打印的错,那么,就只能是我错了,那又是为什么呢?为什么要用二级指针?
接下来是重点了,是我自己对这个问题的想法,但身边没什么人可问,也不敢肯定,所以就来发贴了,我是这样想的:

我们都知道,C语言的函数调用有传值和传址之分,将一个常规变量的地址传递给一个相应类型的指针形参,那么,就可以改变这个变量的值,而直接将这个变量传过去,却是不行,因为传值的思想是“将变量复制多一份”,那么,对于指向结构体的指针,是不是也一样呢?我们虽然传的是指针,但实际上,传的是这支针所指向的结构体的未知地址(因为还没初始化,定义的时候系统随机分配空间,所以说不知这支针指向何处,用未知地址来表达不知可不可以),所以我们在初始化函数中修改到的并不是这支针,而是这支针所指向的结构体,所以,要达到初始化的目的,我们要传的,是这支针的地址,才能达到修改这支针的目的。

我是这样想,自己感觉好像也说得过去,但就是不敢肯定,请各位大虾解答解答。
...全文
197 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
michael122 2010-03-24
  • 打赏
  • 举报
回复
一级指针是带不回去的,lz那样做没有修改实参的值
要达到目的,要么用二级指针,或者用指引的引用
sageking2 2010-03-24
  • 打赏
  • 举报
回复
你在调用InitList里对链表定义估计是
struct sNode *p; /*此时p是指向一个节点(struct sNode )类型的指针*/
InitList(p); /*如果用InitList(struct sNode *HL)的形式,那么是相同类型的变量,会出现变量拷贝,也就是HL也指向p指向的那个节点,InitList()内部执行了HL=NULL;是不会影响P指针的*/

/*如果用InitList(struct sNode **HL)的形式,那么不用变量拷贝,也就是*HL指向p,InitList()内部执行了**HL=NULL;则会改变P指针的指向,达到改变指向内容的目的*/



void InitList(struct sNode **HL)
{
**HL=NULL; /*我认为第一个初始化应该有两个星号*/
}

michael122 2010-03-24
  • 打赏
  • 举报
回复
一级指针是带不回去的,lz那样做没有修改实参的值
要达到目的,要么用二级指针,或者用指引的引用
xiuxianshen 2010-03-24
  • 打赏
  • 举报
回复
canoe982 2010-03-24
  • 打赏
  • 举报
回复
用二级指针,只是因为在初始化时要为这个单链表建立一个专门的头指针,而与参数传递没有直接的关系。
一般是这样写代码的吧?


void InitList(struct sNode *HL)
{
HL=(struct sNode *)malloc(sizeof(struct sNode));
HL->next = NULL;
}
adugmin 2010-03-24
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 mq_shengzhe 的回复:]
这个函数的作用是初始化链表头,就是要初始化这个HL这个指针.

void InitList(struct sNode *HL)
这个函数,执行的时候就是初始化了它的指向.
21: HL = NULL;
00402088 mov dword ptr [ebp+8],0

void InitList(struct sNode **HL)
这个函数,因为传过来的是指向链表头的指针,就等于……
[/Quote]

我觉得是对的呵呵,非常感谢各位
jackylvm 2010-03-24
  • 打赏
  • 举报
回复
这个函数的作用是初始化链表头,就是要初始化这个HL这个指针.

void InitList(struct sNode *HL)
这个函数,执行的时候就是初始化了它的指向.
21: HL = NULL;
00402088 mov dword ptr [ebp+8],0

void InitList(struct sNode **HL)
这个函数,因为传过来的是指向链表头的指针,就等于对链表头赋值.
26: *HL = NULL;
004020B8 mov eax,dword ptr [ebp+8]
004020BB mov dword ptr [eax],0


执行时的汇编代码
37: sNode* p = NULL;
004020F8 mov dword ptr [ebp-4],0 //dword ptr [ebp-4]地方就是0

38:
39: InitList(p);
004020FF mov eax,dword ptr [ebp-4] //eax里面就是0
00402102 push eax //参数传过去的是0,并不是p的地址
00402103 call @ILT+730(InitList) (004012df)
00402108 add esp,4
40: InitList(&p);
0040210B lea ecx,[ebp-4] //得到p的有效地址
0040210E push ecx //这里传过去的才是真正p
0040210F call @ILT+745(InitList) (004012ee)
00402114 add esp,4

不知道我的理解对不对,仅供参考
shanno 2010-03-24
  • 打赏
  • 举报
回复
case1:
void InitList(struct sNode **HL)
{
*HL=NULL;
}

case2:
void InitList(struct sNode *HL)
{
HL=NULL;
}

不要把指针过分地特殊化,其实 struct sNode* HL;中HL是一个指针变量。当调用函数,传递指针变量的时候,它也跟传递普通变量一样要临时拷贝指针变量。所以case2中函数内部的HL并非调用函数时的实参。所以HL = NULL;不会传递回实参。同样地,case1中二级指针变量HL也是一个临时变量。但是由于HL是一个二级指针,所以*HL是不变的,对*HL赋值可以传回实参。



lwjxtx 2010-03-24
  • 打赏
  • 举报
回复
看不懂呢,唉,也得学习了

33,008

社区成员

发帖
与我相关
我的任务
社区描述
数据结构与算法相关内容讨论专区
社区管理员
  • 数据结构与算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧