【C语言】指针的指针在链表节点插入的注意事项

本文探讨了在C语言中如何正确处理形参和实参,特别是在涉及结构体、指针和链表操作时遇到的问题。作者揭示了在函数间传递指针时的传值与传址区别,并提供了针对结构体尾插入操作的代码示例。关键问题在于理解指针的传递方式,最终解决方案是调整参数类型并确保地址操作的持久性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

提示:我们知道C语言中,函数的参数表,总体上分为形参和实参,形参即:将函数1中变量A的值复制一份给到函数2的变量B中,函数2区域内对变量B修改不会改变函数1中的变量A,实参则是:将函数1中变量A的地址复制到函数2的指针变量B中,在函数2范围内对B所指地址的值修改,函数1中的变量A也会被改变。

但我出现的问题却复杂一点,涉及到结构体、指针、单链表及其尾插入节点;

所以让我把代码要实现的过程及其目的简明一下:

  1. 主函数中创建List * 类型的L1,将其作为单链表的头结点
  2. L1传递给函数operator,该函数作为对L1进行各种操作的汇总函数;
  3. 函数operator中创建List * 类型的temp(作为链表L1的尾部指针),以及要插入链表的intitem
  4. L1赋值给temp,并将输入数值给item
  5. temp以及item传入sert函数中,执行表尾插入;
  6. sert函数中新建List * 类型的p(不同函数之间的变量名可以重复),并将item赋值给p->datap->next赋值为NULL
  7. 随后我们要让temp后面链接上p,而temp则要等于p(使temp一直指向链表L1的尾部);

问题描述:

问题出在上述过程7中,在代码中我令temp->next=p(链表尾部链接上p),再使temp=p(temp指向新的尾部p);
但是执行完sert函数后,返回operator函数temp的值没有等于p的值(sert函数中的List类型节点指针);

问题代码如下:

struct List {
	int data;
	struct List* next;
};

typedef struct List* list;
void operator(list L1);
void sert(list p, int item);



int main()
{
	list L1= (list)malloc(sizeof(struct List));
	operator(L1);


	return 0;
}

void operator(list L1)//对链表L1操作的函数
{
	list temp = L1;
	int item;
	scanf("%d", &item);
	sert(temp, item);

	printf("%d", temp->data);
}

void sert(list temp, int item)//插入函数,将item插入尾结点节点p后,并将p指向item所在节点
{
	list p = (list)malloc(sizeof(struct List));
	p->data = item;
	p->next = NULL;
	temp->next = p;
	temp = p;//问题出现部分
}

原因分析:

为什么temp的值在执行sert函数后没有得到改变,在sert函数中我明明设置传入的temp是指针类型的,属于“实参”啊?

经过我的编译器的调试,我发现虽然operator函数中的temp没有改变,但发现temp->next->data的值是我要插入表尾的节点的item值;

所以我确定和sert函数的参数表的传值以及传地址有关;

具体原因:

因为sert函数的参数struct List*temp传入的是operator函数temp的副本,其作用区域只在sert函数范围内,所以operator函数中的temp不被改变,而节点p(sert函数)能链接上L1尾部,是因为temp的值是地址,而地址存放在内存中的堆区,只能被free()掉,在sert函数中(temp->next = p;)实际含义是:通过指针变量temp访问其中地址的next,并将指针变量p的值(地址)赋值给next;而(temp = p;)实际含义是:将sert函数的指针变量p的值赋值给临时指针变量temp(于是一离开sert函数临时指针变量temp就给释放掉了,自然不会影响operator函数中的temp)。

解决方案:

修改后的代码:

void operator(list L1)
{
	list temp = L1;
	int item;
	scanf("%d", &item);
	sert(&temp, item);//传入temp的地址

	printf("%d", temp->data);
}

void sert(list *p, int item)//将list p,改为list *p
{
	list temp = (list)malloc(sizeof(struct List));
	temp->data = item;
	temp->next = NULL;
	(*p)->next = temp;//p表示operator函数中temp指针的地址
	*p = temp;//*p表示间接访问operator函数中temp指针,并代表其
}

sert函数参数表中的struct List *p改为struct List **p,也就是将指针类型改为指向指针的类型;(其它改变如上图所示)

sert函数原本只是对指针的值进行操作,作为传递后指针也属于形参,不会改变原来operator函数指针变量,所以要传入存放指针变量的地址(指针的指针),然后改变这个地址中的值,才会改变operator函数指针变量的值。

指导文章:

C语言的内存分区与malloc函数的用法
如何理解指针的指针?什么情况下使用?
这两篇文章在解决该问题的思路上给了我很多的帮助。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值