关于链表问题, 什么时候用2级指针, 什么时候用1级指针?

cart55free99 2011-03-10 10:27:41
我有一个很基本的问题, 比如说一个函数B想操作函数A中的变量
那么函数A必须把这个变量的地址传入到函数B中,对么?

所以在下面的createLink方法中 因为是对main函数中的*head分配内存 所以mian函数传入了head指针的地址。
因为是指针的地址, 所以createLink 方法才会用二级指针来接受?

void main(){
Stu *head;
createLink( &head ); //在为链表开辟空间的时候要传入指针的地址 createLink函数中的参数应该是2级指针

printf("%d\n",head );

//同样的道理, 为什么在添加节点的时候不用二级指针又可以呢? 不都是在外面的函数中操作本函数的变量嘛?
//这种添加新节点的方式 难道不应该和createLink2一样失败么? 为什么又可以呢?
addNode(head, 3);
addNode(head,4);
addNode(head,5);

printf("\n");
printLink(head);

}

bool createLink(Stu **p ){
if ((*p=( struct Stu *) malloc(sizeof(Stu))) == NULL )
{
return false;
}else{
(*p)->next=NULL; // 这个条件表示 *p 所指向的节点最后一个节点
(*p)->stuNo=-1;
return true;
}
}

//这是错误方法=============================================================================
int createLink2(Stu *p ){
if ((p=( struct Stu *) malloc(sizeof(Stu))) == NULL )
{
return false;
}else{
p->next=NULL;
return true;
}
}

void addNode(Stu *p,int value ){
Stu *n; //新节点
// 经过这么一个循环 p应该是最后一个节点了
while ( p->next!=NULL )
{
p=p->next;
}

//新节点
n=( struct Stu *) malloc(sizeof(Stu));
n->stuNo=value;
strcpy(n->stuName, "str" );
n->next=NULL; // 注意这句话不能省去 // 否则会有不能引用0X.... 的报错

//连接上新节点
p->next=n;
}


void printLink(Stu *p ){
printf("==================\n" );
while ( p->next!=NULL)
{
printf("%d\n",p->stuNo );
p=p->next;
}
printf("%d\n",p->stuNo );
}

...全文
1467 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
wulei7528 2012-07-15
  • 打赏
  • 举报
回复 2
我做个总结 顺便回答一下你的疑问
在main函数开始 你的head指针没有初始化是未定义值 而createLink函数中动态申请了空间,并让head指针指向了这片空间,从而改变了head指针的值,故这里的参数必须为head的地址即二级指针,这样才能对head值进行修改;
对于addLink函数,由于head在createLink的过程中已经指向了第一个结点,此时的添加操作都是在已有的结点之后,且并未修改head的指向,故参数只需为head本身即一级指针。
7楼的意思是说addLink函数如果每次都是在链表的头部插入一个结点,则会使得head指向一个新的结点,而不是在已有结点之后添加结点,楼主的理解有误。
综上,只要是要修改head指针必须传递head的地址,否则传递head值即可。这与普通变量类似,当需要修改普通变量的值,需传递其地址,否则传递普通变量的值即可。
Damn_boy 2011-03-12
  • 打赏
  • 举报
回复
你想在函数中修改什么类型的变量,就传一个那种变量对应的指针就行。
实参就是那个变量的地址
赵4老师 2011-03-11
  • 打赏
  • 举报
回复
指针即地址。但地址是啥就只能从汇编语言和计算机组成原理的角度去解释了。
cart55free99 2011-03-11
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 zhao4zhong1 的回复:]

指针即地址。但地址是啥就只能从汇编语言和计算机组成原理的角度去解释了。
[/Quote]
可是我不明白那么深刻的东西
我想知道根据7楼的回复 我在加第一个节点的时候也就是对head指针指向的节点在操作,
7楼说“ 如果你是从头插入,要改动头指针,那还是得传头指针的地址”
也就是在加上第一个节点的操作和别的节点不一样
根据他的说法 若是想外部方法加上第一个节点 应该传 &head

但是我所有节点的添加都是一个方法 也就是传head 但是这样竟然节点都添加了(至少通过 printLink方法可以打印出添加的节点)

这是怎么回事呢?
cart55free99 2011-03-11
  • 打赏
  • 举报
回复
是不是这样

在另一个函数中改变指针指向的变量 传指针就OK
在另一个函数中为指针指向的变量分配内存空间 传指针的地址?
guixuhui2 2011-03-10
  • 打赏
  • 举报
回复
void main(){
Stu *head;
createLink(head ); //在为链表开辟空间的时候要传入指针的地址 createLink函数中的参数应该是2级指针

printf("%d\n",head );

//同样的道理, 为什么在添加节点的时候不用二级指针又可以呢? 不都是在外面的函数中操作本函数的变量嘛?
//这种添加新节点的方式 难道不应该和createLink2一样失败么? 为什么又可以呢?
addNode(head, 3);
addNode(head,4);
addNode(head,5);

printf("\n");
printLink(head);

}

//这是错误方法
//把createLink( &head ); 改成createLink( head );就正确了。
=============================================================================
int createLink2(Stu *p ){
if ((p=( struct Stu *) malloc(sizeof(Stu))) == NULL )
{
return false;
}else{
p->next=NULL;
return true;
}
}

一下是我粗略写的,你可以试试。

#include<stdio.h>
#include<stdlib.h>

typedef struct linknode{

int data;
struct linknode *next;

}* LNode;

LNode createlink(LNode ptr){

int e;
scanf("%d",&e);
ptr=(LNode)malloc(sizeof(struct linknode));
if(ptr==NULL){

return NULL;
}
else{
ptr->data=e;
ptr->next=NULL;
}

return ptr;

}

int main(){

LNode ptr1=NULL,ptr2=NULL;
ptr2=createlink(ptr1);
printf("%d",ptr2->data);
return 0;
}






zzmlake 2011-03-10
  • 打赏
  • 举报
回复 2
看你要修改的是什么
你创建的时候,要对头指针修改,当然要传头指针的地址,也就是一个指针的指针了
而插入时,是创建一个新的结点,插到后面去,没有对头指针修改,当然不用传头指针的地址了。
话说回来,如果你是从头插入,要改动头指针,那还是得传头指针的地址
赵4老师 2011-03-10
  • 打赏
  • 举报
回复
VC调试时按Alt+8,TC或BC用TD调试,打开汇编窗口看每句C对应的汇编不就啥都明白了吗。
(Linux或Unix下应该也可以在用GDB调试时,看每句C对应的汇编。)
想要从本质上理解C指针,必须学习汇编以及C和汇编的对应关系。
从汇编的角度理解和学习C语言的指针,原本看似复杂的东西就会变得非常简单!
lx3275852 2011-03-10
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 cart55free99 的回复:]


那么在添加节点的时候不用2级指针是否是因为 我是修改了该指针p所指向的节点的next方向,并不是修改p的指向, 所以是就用1级指针就可以
[/Quote]

没错,什么时候需要修改传过来参数的值,就接受它的指针来间接修改!~
cart55free99 2011-03-10
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 lx3275852 的回复:]

想要在函数里修改一级指针的指向,就要用2级指针接收,间接修改一级指针内容

只读操作,不修改一级指针的内容,就用1级指针就可以。。。。
[/Quote]

那么在添加节点的时候不用2级指针是否是因为 我是修改了该指针p所指向的节点的next方向,并不是修改p的指向, 所以是就用1级指针就可以
碎碎念 2011-03-10
  • 打赏
  • 举报
回复
[Quote=引用楼主 cart55free99 的回复:]
因为是指针的地址, 所以createLink 方法才会用二级指针来接受?
[/Quote]
是这样的...
这样是为了在函数中可以修改这个指针...
lx3275852 2011-03-10
  • 打赏
  • 举报
回复
想要在函数里修改一级指针的指向,就要用2级指针接收,间接修改一级指针内容

只读操作,不修改一级指针的内容,就用1级指针就可以。。。。
justkk 2011-03-10
  • 打赏
  • 举报
回复
[Quote=引用楼主 cart55free99 的回复:]
所以在下面的createLink方法中 因为是对main函数中的*head分配内存 所以mian函数传入了head指针的地址。
因为是指针的地址, 所以createLink 方法才会用二级指针来接受?
[/Quote]
对的√
cart55free99 2011-03-10
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 zzmlake 的回复:]

看你要修改的是什么
你创建的时候,要对头指针修改,当然要传头指针的地址,也就是一个指针的指针了
而插入时,是创建一个新的结点,插到后面去,没有对头指针修改,当然不用传头指针的地址了。
话说回来,如果你是从头插入,要改动头指针,那还是得传头指针的地址
[/Quote]

那我在添加第一个节点的时候 算是在head后面加入吗?但是我没有传头指针的地址?还是添加进去了
而且书上说的是这样的,
“通常 在线形链表第一个头结点之前设一个称为头结点的节点,这个节点不装任何数据”
照书上这样来说 就是传head 就OK, 这样也就是和你的说法一致。

假如我是在main函数中在head之后设了一个头结点, 里面不装任何数据。
那么添加节点的时候就是在修改 head指向的这个空数据的头结点 的next
因此没有修改头结点本身

按照你的说法 是这样的
问题在于我的第一个实际的节点就是直接接在head后面的,
而且我所有的节点添加都是一个方法 , 通过传入的head 而不是*head
这和上面的说法矛盾了
但是程序运行没有报错?
而且没有报错,应该来说是要报错才对。。。为什么呢?

baibai00a 2011-03-10
  • 打赏
  • 举报
回复
试时按Alt+8,TC或BC用TD调试,打开汇编窗口看每句C对应的汇编不就啥都明白了吗。
(Linux或Unix下应该也可以在用GDB调试时,看每句C对应的汇编。)
想要从本质上理解C指针,必须学习汇编以及C和汇编的对应关系。
从汇编的角度理解和学习C语言的指针,原本看似复杂的东西就会变得非常简单!
cart55free99 2011-03-10
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 zhao4zhong1 的回复:]

VC调试时按Alt+8,TC或BC用TD调试,打开汇编窗口看每句C对应的汇编不就啥都明白了吗。
(Linux或Unix下应该也可以在用GDB调试时,看每句C对应的汇编。)
想要从本质上理解C指针,必须学习汇编以及C和汇编的对应关系。
从汇编的角度理解和学习C语言的指针,原本看似复杂的东西就会变得非常简单!
[/Quote]

汇编窗口是什么啊? 我的英文的VC , 不知道那一个是啊

70,038

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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