【问题标题】:Link List Generation with malloc()使用 malloc() 生成链接列表
【发布时间】:2018-10-13 20:40:26
【问题描述】:

如何在链表生成中使用 malloc?我看不到它是如何用于生成链表的,而不是为链表保留内存

提示:按Ctrl + F 并查找“(***)”(不带引号)以找到确切的代码位置

示例 1:

#include <stdio.h>
#include <stdlib.h>

struct LinkedList {
    int data;                   /* The data part of the linked list */
    struct LinkedList *next;    /* The pointer part of the linked list */
};  

int main(void) {

    /* Generate the 1st node ("head")  */
    struct LinkedList *head     /* I am not sure what this pointer */  
    head = NULL;                /* is doing to the struct*/
    head = malloc(sizeof(struct LinkedList));   /* Head points to null. Now
                                                 * malloc() is being called  
                                                 * and is assigned to head. 
                                                 * Next line implies head is 
                                                 * already pointing to a 
                                                 * linked list, which means 
                                                 * malloc() is making a new 
                                                 * strucuture (***) */

    /* Generate the second node */
    head -> data = 1; // This implies head is already pointing to a linked list
    head -> next = malloc(sizeof(struct LinkedList));

    /* Generate the third node */
    head -> next -> data = 2;
    head -> next -> next = malloc(sizeof(struct LinkedList));

    /* Generate the fourth node */

    head -> next -> next -> data = 3;
    head -> next -> next -> next = NULL;

    return 0;
}

示例 2:

#include<stdio.h>
#include<stdlib.h>

struct LinkedList {
    int data;
    struct LinkedList *next;
}; // notice the semi-colon!


int main(void) {

    struct LinkedList *head = NULL;     /* why is it doing this? */
    struct LinkedList *second = NULL;
    struct LinkedList *third = NULL;

    // Generate the node structure:
    /* how does (struct LinkedList*) affect malloc? (***) */
    head = (struct LinkedList*)malloc(sizeof(struct LinkedList));
    second = (struct LinkedList*)malloc(sizeof(struct LinkedList));
    third = (struct LinkedList*)malloc(sizeof(struct LinkedList));

    // Now fill the first node with info:
    head->data = 1;         /* assign data to the first node */
    head->next = second;    /* Link the first node ("head") with the second 
                             * node ("second") */

    // Now fill the second node with info:
    second->data = 2;       /* assign data to the second node */
    second->next = third;   /* Link the second node to the third node */

    // Now fill the second node with info:
    third->data = 3;        /* assign data to the second node */
    third->next = NULL;     /* Since node 3 is our last node to the link list, 
                             * we give it the value of NULL */

    return 0;
}

教科书将链表描述为链式结构。 Malloc() 用于动态内存管理。但是,在这些示例中,malloc 被用于声明一个新结构,我不明白为什么。我以为它只保留内存

例如,在示例 1 中,malloc() 为结构保留空间,但不“创建”它(struct LinkedList var 将创建一个新的链表并将其存储在 var 中)

例如,在示例 2 中,malloc() 似乎受到(struct LinkedList*)(即(struct LinkedList*)malloc(sizeof(struct LinkedList));)的影响,但我不确定

【问题讨论】:

  • malloc 未被用于“声明”该代码中的任何内容。它被调用以在堆上分配存储。链表中的节点是指针的结构。必须分配内存来保存指针指向的节点。
  • 没有必要从malloc 转换返回值,但这基本上是示例2 中代码所做的,将malloc 返回的void* 转换为类型struct LinkedList*。跨度>
  • 请注意,calloc 可用于分配所需的存储空间并将内存清除为零,因此在需要另一个节点之前,所有指针都已经为 NULL,您只需初始化数据元素。

标签: c malloc


【解决方案1】:

您可以像在相互连接的盒子上一样查看链表:

 ______        ______        ______
| data |      | data |      | data |
|______|      |______|      |______|
| next |      | next |      | next |
|______|----->|______|----->|______|----->NULL

每个盒子都是你的:

struct LinkedList
{
    int data; /* The data part of the linked list */
    struct LinkedList *next; /* The pointer part of the linked list */

};

“盒子”的大小(取决于拱门)让我们以 x64 Linux 机器为例 到 16 个字节。要创建链表数据类型,您需要将此框存储在内存(堆栈/堆)中并连接它们。

我注意到一个“盒子”的大小是 16 字节,它应该存储在内存中。对于用户空间中的内存管理,您可以使用malloc(),这里很重要malloc() 不是“声明”任何东西只分配一部分内存 用于堆上的一个“盒子”,而您使用 sizeof() 运算符为“盒子”请求正好 16 个字节。

struct LinkedList *head = malloc(sizeof(struct LinkedList));

它为你的“盒子”分配内存,现在看起来像这样:

 ______ 
| data |
|______|
| next |
|______|----->NULL

当你这样做时:

head->next = malloc(sizeof(struct LinkedList));

您为另一个“盒子”分配内存并连接它们:

 ______        ______  
| data |      | data |      
|______|      |______|      
| next |      | next |      
|______|----->|______|

当你这样做时:

struct LinkedList *head = malloc(sizeof(struct LinkedList));     
struct LinkedList *second = malloc(sizeof(struct LinkedList));
struct LinkedList *third = malloc(sizeof(struct LinkedList));

您在内存的某处创建了三个“盒子”,每个盒子 16 个字节。而且它们暂时没有连接,它们只位于内存中;

   head         second      third
  ______        ______      _____
 | data |      | data |    | data |
 |______|      |______|    |______|   
 | next |      | next |    | next |
 |______|      |______|    |______|

你把他们联系起来做这个:

head->next = second;
second->next = third;
third->next = NULL;

 head          second        third
 ______        ______        ______
| data |      | data |      | data |
|______|      |______|      |______|
| next |      | next |      | next |
|______|----->|______|----->|______|----->NULL

通常在函数中使用第二种方法,例如 for ex add_node_front()

void add_node_front(struct LinkedList **head_ref, int data) 
{ 
    /* 1. allocate node */
    struct LinkedList *new_node = malloc(sizeof(struct LinkedList)); 

    /* 2. put in the data  */
    new_node->a  = data; 

    /* 3. Make next of new node as head */
    new_node->next = (*head_ref); 

    /* 4. move the head to point to the new node */
    (*head_ref)    = new_node; 
} 

【讨论】:

    【解决方案2】:

    在第二个示例中,您还可以静态分配内存:

    struct LinkedList head;
    struct LinkedList second;
    struct LinkedList third;
    

    那么你需要用点运算符访问:

    head.data = 1; //assign data to the first node
    head.next = &second;
    

    你也可以使用数组

    struct LinkedList nodes[3];
    node[0].data = 1;
    node[0].next = &node[1];
    

    等等。

    因此,malloc 命令对于链表的概念并不是必不可少的。 但是对于许多你以前不知道的应用程序,你的链表会有多大。并且元素和顺序会在运行时发生变化。因此,在这种情况下,使用 malloc/free 进行动态内存分配真的很有帮助。

    【讨论】:

      【解决方案3】:

      如何在链表生成中使用 malloc?

      malloc 用于动态分配内存。在创建链表时,可以使用malloc 为链表的节点分配内存。 阅读有关 malloc 的更多信息here

      来自示例 1:

      head = malloc(sizeof(struct LinkedList));
      

      来自示例 2:

      head = (struct LinkedList*)malloc(sizeof(struct LinkedList));
      

      唯一的区别是,在示例 2 中,您显式地转换了 malloc 结果。 malloc 返回类型是 void *void * 可以转换为所需的类型,但不需要这样做,因为它会自动转换。所以演员表是没有必要的。事实上,将malloc 返回是不可取的。检查this

      除了内存分配顺序外,您的两个示例在功能上都是相同的。 在示例 1 中,您将内存分配给 head 指针,然后分配给 head -&gt; next 指针,然后分配给 head -&gt; next -&gt; next 指针。

      在示例 2 中,您将内存分配给 headsecondthird 指针,然后将 second 分配给 head -&gt; nextthird 分配给 head -&gt; next -&gt; next


      补充:

      始终检查 malloc 返回,如下所示:

      head = malloc(sizeof(struct LinkedList));
      if (NULL == head) {
          fprintf (stderr, "Failed to allocate memory");
          exit(EXIT_FAILURE);
      }
      

      此外,请确保在使用完动态分配的内存后free。遵循良好的编程习惯。

      【讨论】:

        猜你喜欢
        • 2010-12-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-03-23
        • 2022-12-22
        • 2019-05-04
        • 1970-01-01
        • 2016-08-25
        相关资源
        最近更新 更多