C修改函数的指针型形参对其实参的影响

本文通过一个LeetCode问题引发的思考,探讨了C语言中函数参数传递时指针类型变量的变化。作者发现直接通过指针修改链表节点可能导致实参不变,解决办法是使用解引用操作`*`来正确修改指针所指向的值。实验结果验证了解引用后的代码能够正确影响实参。
摘要由CSDN通过智能技术生成

文章首发及后续更新:https://mwhls.top/1533.html
新的更新内容请到mwhls.top查看。
无图/无目录/格式错误/更多相关请到上方的文章首发页面查看。

这一次的Leetcode题又给我贡献了两篇文章,太棒了!

前言

在做Leetcode第21题时,原本觉得有些代码重复调用了,就想弄成函数形式,是这个作用:
传参两个链表结点,比较值的大小,将值小的作为返回值,并将该指针后移一个结点。
但在使用中,出现无限循环,测试发现是因为函数内虽然后移了指针,但实参并不受影响。
因此好奇这是Leetcode编译器的特性还是我的C理解不到位。
于是有了这次测试,测试的结果,的确是我学的不到位了。

原测试代码
  • 代码使用两个结点进行测试,分别是:
    • 结点1:val==1,next指向结点2,结点1是头结点。
    • 结点2:val==2,next指向NULL。
  • 代码中会先输出头结点的值及其地址,
    • 再通过nextNode将头结点后移,并输出其值及其地址,
      • 再返回主函数继续输出头结点的值及其地址。
#include <stdio.h>

struct ListNode{
	int val;
	struct ListNode* next;
};

void nextNode(struct ListNode* node);

int main(){
	struct ListNode* testNode = (struct ListNode*)malloc(sizeof(struct ListNode));
	testNode->val = 1;
	testNode->next = (struct ListNode*)malloc(sizeof(struct ListNode));
	testNode->next->val = 2;
	testNode->next->next = NULL;
	printf("val: %d, pointer: %p, next pointer:%p\n", testNode->val, testNode, testNode->next);
	nextNode(testNode);
	printf("val: %d, pointer: %p, next pointer:%p\n", testNode->val, testNode, testNode->next);
}

void nextNode(struct ListNode* node){
	node->val = 3;
	node = node->next;
	printf("val: %d, pointer: %p, next pointer:%p\n", node->val, node, node->next);
}
结果分析

运行结果如下:

val: 1, pointer: 00000000007313E0, next pointer:0000000000731400
val: 2, pointer: 0000000000731400, next pointer:0000000000000000
val: 3, pointer: 00000000007313E0, next pointer:0000000000731400
  • 可以看出:
    • 第一次,在主函数中输出第一个结点的信息,
    • 第二次,在函数内部输出第二个结点的信息,
    • 第三次,返回主函数输出第一个结点的信息。
  • 即通过nextNode函数后移结点后,虽然函数内部形参发生了变化,但实参并没有改变。
    • 这与我的认知不同,修改指针型的形参理应影响实参。
    • 然后回想了下我几个月没碰的C语言,想起了似乎是还需要加*。
    • 于是修改了nextNode函数,进行了新一次测试。
      • 即,将node = node->next;修改成了*node = *node->next;
新测试代码

代码仅将nextNode函数中的node = node->next;修改成了*node = *node->next;

#include <stdio.h>

struct ListNode{
	int val;
	struct ListNode* next;
};

void nextNode(struct ListNode* node);

int main(){
	struct ListNode* testNode = (struct ListNode*)malloc(sizeof(struct ListNode));
	testNode->val = 1;
	testNode->next = (struct ListNode*)malloc(sizeof(struct ListNode));
	testNode->next->val = 2;
	testNode->next->next = NULL;
	printf("val: %d, pointer: %p, next pointer:%p\n", testNode->val, testNode, testNode->next);
	nextNode(testNode);
	printf("val: %d, pointer: %p, next pointer:%p\n", testNode->val, testNode, testNode->next);
}

void nextNode(struct ListNode* node){
	node->val = 3;
	*node = *node->next;
	printf("val: %d, pointer: %p, next pointer:%p\n", node->val, node, node->next);
}
第二次结果分析

运行结果如下:

val: 1, pointer: 0000000000A213E0, next pointer:0000000000A21400
val: 2, pointer: 0000000000A213E0, next pointer:0000000000000000
val: 2, pointer: 0000000000A213E0, next pointer:0000000000000000
  • 结果与预想的一致,函数内部修改形参后反馈到了实参。
总结
  • 在通过函数修改指针形参时,要注意是否加了*,
    • 不加*,修改的是地址值,
    • 加了*,修改的才是地址对应的值。
  • 尤其是修改链表、树这一类数据结构时要注意。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值