自从我开始学习数据结构一两个月后,使用C
,我一直在遵循编写链表的特定方法。看起来像这样。
#include<stdio.h>
#include<stdlib.h>
struct Node{
int exponent;
int coeff;
struct Node *next;
};
typedef struct Node N;
N *st = NULL;
void insert(N *node, int c, int e){
N *temp;
node->exponent = e;
node->coeff = c;
if(st == NULL){
node->next = st;
st = node;
} else {
temp = st;
while(temp->next != NULL){
temp = temp->next;
}
node->next = temp->next;
temp->next = node;
}
printf(" %p", st); //this is written on purpose, not that i write it everytime
}
我从主方法中调用它,
N *node = malloc(sizeof *node);
insert(node, 1, 2);
四次此类调用的printf输出为
00340D18 00340D18 00340D18 00340D18
,即开始指针的值保持不变,但如果我在代码中进行了一些小改动
typedef struct Node N;
void insert(N *node, N *st, int c, int e){
N *temp;
node->exponent = e;
node->coeff = c;
if(st == NULL){
node->next = st;
st = node;
} else {
temp = st;
while(temp->next != NULL){
temp = temp->next;
}
node->next = temp->next;
temp->next = node;
}
printf(" %p", st);
}
并在main方法中声明开始指针
N *strt = NULL;
node = malloc(sizeof *node);
insert(node, strt, 1, 1);
然后像前一种情况一样运行四次,启动指针的值会发生变化
每次通话后
00560D18 00560D30 00560D48 00560D60
为什么会这样? 如果我想将开始指针作为参数传递应该进行哪些更改?
答案 0 :(得分:4)
为什么会这样?
这是因为对st
的更改对调用方是不可见的。即st = node
对调用者没有任何影响。该函数更改自己的副本,在函数返回后,如果调用者打印strt
,它仍然是NULL
。
这是一个有点微妙的结果,因为C参数是通过值传递的,甚至是指针。所以你按价值传递strt
。您可以更改st->whatever
,因为它是一个指针,更改将传播给调用方,但更改strt
本身将无效。
如果我想将开始指针作为参数传递更改 应该制作
这是此网站上的常规问题,还有C FAQ来描述问题。你可以做的一个简单但有点麻烦的改变就是让函数占用一个
N **st
并传递&strt
。
答案 1 :(得分:1)
这是因为strt
方法中的main
和修改后的函数st
中的insert
是两个不同的变量。函数调用
insert(node, strt, 1, 1);
将strt
中定义的main
的值复制到函数参数st
,这是一个不同的变量,并在函数insert
为时在堆栈上分配调用。对st
所做的任何更改在函数内部都是可见的,因为它是一个局部变量。一旦函数返回,它就会超出范围。因此,strt
中定义的main
仍然指向null并且永远不会更改。这意味着条件st == NULL
始终为true,并且if
中的insert
块始终执行,并且每次函数时局部变量st
都设置为新创建的节点调用insert
。事实上,这会导致内存泄漏,因为一旦函数insert
返回,您将丢失节点上的句柄。
您应该做的是将变量strt
的地址传递给insert
,以便在main
中显示对其所做的更改。由于您始终将新节点附加到链接列表的末尾,因此我建议您进行一些更改。
void insert(N *node, N **st, int c, int e) {
N *temp = *st;
node->exponent = e;
node->coeff = c;
node->next = NULL; // set it explicitly to NULL
if(*st == NULL) { // if head of the linked list is NULL
*st = node;
}
else {
while(temp->next != NULL) // reach the end of the linked list
temp = temp->next;
temp->next = node; // add the new node at the end
}
printf("%p", *st);
}
在main
中,将函数调用为
// in main method
N *strt = NULL;
node = malloc(sizeof *node);
insert(node, &strt, 1, 1);