我不完全理解c中的列表是如何工作的

t40tm48m  于 2023-03-17  发布在  其他
关注(0)|答案(1)|浏览(101)

我试着在列表的开头添加一个元素,函数prepend_list在第27行,我试着用两种不同的方法,一种是返回一个列表,另一种是void函数。

#include "base.h"
#include "string.h"

typedef struct Node Node;
struct Node{
    int value;
    Node* next;
};

Node* new_node(int value, Node* next){
    Node* new = xmalloc(sizeof(Node));
    new->value = value;
    new->next = next;
    return new;
}

void free_list(Node* list){
    Node* currentHead = list;
    while(list != NULL){
        currentHead = list;
        list = list->next;
        free(currentHead);
    }
}

Node* prepend_list(int value, Node* list){
    return new_node(value, list);
}

void test(void) {
    Node* n = NULL;
    n = new_node(1, new_node(3, NULL));
    n = prepend_list(2, n);
    for(Node* print = n;print != NULL;print = print->next){
        printi(print->value);
        if(print->next != NULL){
            prints(", ");
        }
    }
    printsln("");
    free_list(n);
}

int main(void) {
    test();
    report_memory_leaks(true);
    return 0;
}

但我不明白为什么我不能这样做

void prepend_list(int value, Node* list){
    list = new_node(value, list);
}

当我试着这样做的时候,test函数中的list n根本没有改变,相反,我得到了内存泄漏,有人能告诉我为什么吗?

cqoc49vn

cqoc49vn1#

函数处理作为参数传递给函数的表达式值的副本。
你可以想象

void prepend_list(int value, Node* list){
    list = new_node(value, list);
}

它的召唤

Node* n = NULL;
prepend_list(2, n);

以下方式

prepend_list(2, n);
//...
void prepend_list(/* int value, Node* list */){
    int value = 2;
    Node* list = n;
    list = new_node(value, list);
}

正如你所看到的,函数的局部变量列表是由传递过来的指针n的值初始化的,在函数内部,被改变的是局部变量列表,指针n保持不变,也就是说函数接受参数的值.
有两种方法可以解决此问题并更改原始指针。
第一个是从函数中返回一个新指针,然后把它赋值给原来的指针,就像在程序中一样。

n = prepend_list(2, n);

第二种是通过引用传递原始指针,间接地通过一个指向它的指针,并且解引用指向原始指针的指针,这个函数可以访问原始指针,并且可以改变它,例如

prepend_list(2, &n);
//...
void prepend_list(int value, Node ** list){
    *list = new_node(value, *list);
}

相关问题