一、目标
主要理清,在C语言中一个void方法里,当参数分别传入指针、地址、值三种选择时,我应该怎么选择传什么样的参数?哪种情况下结果会被带回?以及出现这种情况的原因。本篇文章我会用一个例子来说明。
例子:实现单链表的原地逆置
二、内容
变量定义
typedef struct LNode{
int data;
LNode *next;
}LNode,List;
(1) 情形一
//单链表的原地逆置
void reverse(List list){
LNode* p;
p = list.next;
list.next = nullptr;
while(p!=nullptr){
LNode* temp = p->next;
p->next = list.next;
list.next = p;
p = temp;
}
}
结果是这样的:
(2) 情形二
将上述函数参数改为如下,方法体不动
void reverse(List &list)
得到正确结果
(3)情形三
将函数参数改为指针,相应的list.xxx改为list->xxx
//单链表的原地逆置
void reverse(List *list){
LNode* p;
p = list->next;
list->next = nullptr;
while(p!=nullptr){
LNode* temp = p->next;
p->next = list->next;
list->next = p;
p = temp;
}
}
得到正确结果
三、描述
1、情形一
传入的是List(头结点)。说明我对结点的改动是生效的,但是头结点(List)并没有把结果带回,头结点(List)的下个结点依然是0,应该是012,但0后面断了,是因为012的顺序发生了改变是生效的!变成了210。所以0后面不再有结点。
2、情形二
传的是List的地址。头结点(List)的改动被带回。
3、情形三
传入的是指向List(头结点)的指针。头结点(List)的改动被带回。
四、分析
1、情形一是值传递,形参与实参并不共用地址单元,是独立的。形参改变实参不受影响。
2、情形二是地址传递,形参与实参共用地址单元,或者说形参就是实参本身。
3、情形三
其实是值传递,不过传的是指针的值,然而我们的操作实际上并没有让指针发生改变(依然是指向头结点)。而是指针所指的地址内容发生变化(他们所指向的内存单元相同)。因此,借助形参list改变的内容可以被带回!
这也解释了情形一中。为什么在没被带回改变的情况下,却从 "头012",变化成了 "头0"。
因为012结点之间的顺序是用指针指向的。012已经变成210!只是形参头结点没有被带回实参,实参依然指向的是0,而0却已经是指向null的结点了!!
五、总结
无论是传指针、地址还是值,都是为了也都是可以拿到内容去进行处理的。
我们应该关注的是,内容经过处理后的改变,是否能够被”带回“。
这本质又是一个形参与实参的问题了。
今后在定义函数参数时,根据实际情况,不再迷糊。