前言(Introduction):
最近在学习链表的过程中,我写了这样一段函数:
Recently in the process of learning the linked-list, I wrote a function like this:
/* Add a new item to the list */
int addItem(struct film *head, struct film *prev, char *input){
/* Request memory to store the input and create a pointer to it */
struct film *current = (struct film *) malloc(sizeof(struct film));
/* Judge whether the first node exists */
if (head==NULL){
head = current;
}
else{
prev->next = current;
}
/* Edit the current node */
current->next = NULL;
strcpy(current->title, input);
puts("[INFO] Please input the rating<0-10> here.");
scanf("%d",¤t->rating);
while(getchar()!='\n')
continue;
puts("[INFO] Adding an item successfully.");
/* set the value of pointer for previous node to the value of current pointer */
prev = current;
return 0;
}
很明显,我的目的是为了在链表中添加一个新的节点,并将输入的数据存放进去。
Obviously, I want to add a new node to the linked-list, and save the input to it.
运行整个程序时,我调用该函数能正常完成输入,但是在之后我对链表的所有数据进行遍历输出时,我发现其实数据并没有被存入链表里。
Then I ran the whole program, there was nothing wrong with this function. However, when I had a traversal of this list and output all data, I found that nothing is stored in the list.
问题(The Problem):
那么,问题出在哪里呢?
So, what's the problem?
通过调试,我确认了该函数是正常运行的,所以问题在于函数中的操作并不能正确的完成我想要完成的事情。
After debugging, I made sure that the function ran well, so the problem is that my code is unable to do want I want to do correctly.
随后我在该函数被调用结束后,加上了打印当前head的值和prev的值的函数。
Then I add the function to print the value of "head" and "prev" after the function is executed.
两者的结果都是NULL(NULL是我初始化这两个指针变量时所赋的值)。
The results are both NULL, which is what I set to the two pointers when I initial them.
原因(Cause):
我很迷惑,为什么会这样。重新读了几遍代码,都没有发现问题。那就开始单步调试吧。
I am confused, how can that be. Reading the code again and again, I can't find the problem. So I start to debug step by step.
当我看到一切正常运行到函数结束后,"head"的值突然变回NULL时,我恍然大悟。
When I saw the value of "head" changed back to NULL at the moment that all the things ran well and the function is done, the problem suddenly dawned on me.
我将结构的指针传入函数以便改变结构内部的成员变量的值,但是忘了结构指针本身作为被传入的变量,在函数内部是无法改变其值的。
(原因是, C语言函数中传入的变量仅是与被调用时传入的参数的值相同的一份拷贝,与原变量处于两个不同的存储空间)
In this function, I used the pointer to a struct to change the value of the variable in the struct, but I forgot that the value of the point can't be changed as a variable passed in.
(The reason is that the variable passed in the function is just a copy of the original variable, the memories to store them are different in the C language)
解决方案(Solution):
明确问题之后,修改方案就很容易得出了。
As the problem is clear, it's easy to come up with the solution.
现在我既想改变传入的指针的值,又想能够改变指针指向的成员变量的值,怎么办呢?
Now I want to change the value of the pointer passed in, also want to change the value of the variable in the struct which is pointed by the pointer, how to do that?
二级指针!
The secondary pointer!
所以我修改了代码如下:
So I changed the code as below:
/* Add a new item to the list */
int addItem(struct film **head, struct film **prev, char *input){
/* Request memory to store the input and create a pointer to it */
struct film *current = (struct film *) malloc(sizeof(struct film));
/* Judge whether the first node exists */
if (*head==NULL){
*head = current;
}
else{
(*prev)->next = current;
}
/* Edit the current node */
current->next = NULL;
strcpy(current->title, input);
puts("[INFO] Please input the rating<0-10> here.");
scanf("%d",¤t->rating);
while(getchar()!='\n')
continue;
puts("[INFO] Adding an item successfully.");
/* set the value of pointer for previous node to the value of current pointer */
*prev = current;
return 0;
}
同时将调用该函数时传入的参数改为了指向两个结构的指针的指针。
At the same time, I changed the two parameters to the secondary pointers to the two structs.
运行程序,一切正常。
Run the program, all the things are well.
总结(Conclusion):
回过头来看,这是一个非常简单的问题,但当我在编写和调试这段代码时,始终无法发现问题所在,应了“当局者迷”这句话。当检查代码时,我一直纠结于通过结构指针改变结构体成员变量这一操作,却忽略了结构指针作为参数,本身在传入函数时只是传入了一份与其值相同的拷贝这一问题。所以,当你无法发现你的代码出现了什么问题时,不妨回想一下一些基础概念,也许一切便会豁然开朗。
Looking back on this process, it's a very easy problem, but I can't find that quickly when I am writing and debugging on this code, proving that those closely involved can't see clearly. When checking the code, I focused on the operation that change a variable in the struct through the pointer to the struct, ignoring that the pointer can't be changed as a parameter passed in the function. So, when you can't find what is wrong with your code, why not think back some basic concepts, maybe suddenly you will see the light.