在C中为链表中的新元素分配内存

在C中为链表中的新元素分配内存,c,linked-list,C,Linked List,我正在尝试创建一个链接列表,我已经让它工作了,但是我仍然有点困惑。我正在使用以下结构: typedef struct _MList { int dx; int dy; struct _MList *next; } MList_t, *MList_p; 我已经测试过这种结构是否合理,并且我有一个打印列表的函数: void mListPrint(MList_t *mList) { MList_p node = mList; while (node->n

我正在尝试创建一个链接列表,我已经让它工作了,但是我仍然有点困惑。我正在使用以下结构:

typedef struct _MList
{
    int dx;
    int dy;
    struct _MList *next;
} MList_t, *MList_p;
我已经测试过这种结构是否合理,并且我有一个打印列表的函数:

void mListPrint(MList_t *mList)
{
    MList_p node = mList;
    while (node->next != NULL)
    {
        printf("[%i,%i] ",node->dx,node->dy);
        node = node->next;
    }
    printf("[%i,%i]\n",node->dx,node->dy);
}
以及用于创建第一个节点的函数:

MList_t mListNew(int dx, int dy)
{
    MList_t newNode;
    newNode.dx = dx;
    newNode.dy = dy;
    newNode.next = NULL;    
    return newNode;
}
有了这个功能,我想我应该尝试创建一个函数,在列表的末尾添加一个节点。我的第一次尝试是:

void mListAdd(int dx, int dy, MList_t *mList)
{
    MList_p node = mList;

    while (node->next != NULL)
    {
        node = node->next;  
    }

    MList_t newNode = mListNew(dx,dy);
    node->next = &newNode;
}
这看起来不错,直到我添加了不止一个元素。经过多次调试,在mListAdd中创建的“新节点”的内存地址始终相同。因此,列表最终链接回了自身。为什么会这样

相反,我使用指向新节点的指针实现了mListAdd,如下所示:

void mListAdd(int dx, int dy, MList_t *mList)
{
    MList_p node = mList;

    while (node->next != NULL)
    {
        node = node->next;
    }
    MList_p newNode = malloc(sizeof(MList_t));
    *newNode = mListNew(dx,dy);
    mListPrint(newNode);
    node->next = newNode;
}
这很好,但我觉得另一种方法也应该有效。还是我遗漏了一些明显的东西?我试图通过实现我在Java和ML中学习的不同数据结构来学习C语言,以备面试之用


我很抱歉代码太多,但我认为最好尽可能彻底地解释我的问题。提前感谢您的帮助

必须使用malloc()或calloc()明确分配内存。您要做的是使用只存在于堆栈上的结构,并且在mListAdd返回后不再真正存在;恰好它还没有被覆盖。

您必须使用malloc()或calloc()明确地分配内存。您要做的是使用只存在于堆栈上的结构,并且在mListAdd返回后不再真正存在;碰巧它还没有被覆盖。

第一个示例在堆栈上分配内存,因此它只能在函数内部使用,因此您不应该在可能在函数外部存在的链表中使用它的内存地址。

第一个示例在堆栈上分配内存,因此,它仅在函数内部可用,因此您不应在可能存在于函数外部的链表中使用其内存地址。

mListNew
中,您使用的是局部变量:

MList_t newNode;
当您从函数返回时,这将超出范围。所以你在未定义的领域。这段代码看起来似乎只有在内存管理器没有覆盖该局部变量占用的内存块时才起作用

您应该使用malloc inside
mListNew
分配新的列表节点,并返回指向新节点的指针,如下所示:

MList_p mListNew(int dx, int dy)
{
    MList_p newNode = malloc(sizeof(MList_t));
    newNode->dx = dx;
    newNode->dy = dy;
    newNode->next = NULL;    
    return newNode;
}

mListNew
中,您正在使用局部变量:

MList_t newNode;
当您从函数返回时,这将超出范围。所以你在未定义的领域。这段代码看起来似乎只有在内存管理器没有覆盖该局部变量占用的内存块时才起作用

您应该使用malloc inside
mListNew
分配新的列表节点,并返回指向新节点的指针,如下所示:

MList_p mListNew(int dx, int dy)
{
    MList_p newNode = malloc(sizeof(MList_t));
    newNode->dx = dx;
    newNode->dy = dy;
    newNode->next = NULL;    
    return newNode;
}

抱歉,我确信还有更多,但我没有阅读“和一个创建第一个节点的函数”

新节点是在堆栈上创建的。它的定义是函数mListNew()的本地定义,当它返回时,它是“未定义的”

最佳实践是,您需要呼叫方在呼叫前分配(并释放)内存。例如

void mListNew(int dx, int dy, MList_t *newNode)
{
    newNode->dx = dx;
    newNode->dy = dy;
    newNode->next = NULL;    
}

我还没有看它的其余部分…

对不起,我肯定还有更多,但我没有阅读“和一个创建第一个节点的函数”

新节点是在堆栈上创建的。它的定义是函数mListNew()的本地定义,当它返回时,它是“未定义的”

最佳实践是,您需要呼叫方在呼叫前分配(并释放)内存。例如

void mListNew(int dx, int dy, MList_t *newNode)
{
    newNode->dx = dx;
    newNode->dy = dy;
    newNode->next = NULL;    
}

我还没有看剩下的部分…

谢谢大家。那很快。真希望我能给你们两个打绿旗:)谢谢你们。那很快。但愿我能给你们两个打绿旗:)啊。这一切现在都有意义了。谢谢你啊。这一切现在都有意义了。谢谢你,好的。但根据这个推理,所有内存分配都将在main()中完成?这不会让代码更难阅读吗?好的。但根据这个推理,所有内存分配都将在main()中完成?这难道不会让代码更难阅读吗?