用户定义了破坏(免费)功能

时间:2013-09-29 13:37:15

标签: c linked-list

这是我的第一个问题。我无法理解这个程序中的几行代码。

自定义销毁函数指针是我无法理解的。

我已经评论过“需要帮助#1并需要帮助#2”我需要有关代码的帮助。

非常感谢任何帮助,我将非常感谢能够帮助我理解这些代码的任何人。

#ifndef LIST_H
#define LIST_H
#include <stdio.h>

typedef struct _ListElmt
{

  void *data;
  struct ListElmt *next;

} ListElmt;
typedef struct _List
{

  int size;
  int (*match)(const void *key1, const void *key2);
  void (*destroy)(void *data);

  ListElmt *head;
  ListElmt *tail;

} List;

void list_init(List *list, void (*destroy)(void *data));

void list_destroy(List *list);

int list_ins_next(List *list, ListElmt *element, const void *data);

int list_rem_next(List *list, ListElmt *element, void **data);

int list_size(const List *list);

ListElmt *list_head(const List *list);

ListElmt *list_tail(const List *list);

int list_is_head(const ListElmt *element);

int list_is_tail(const ListElmt *element);

void *list_data(const ListElmt *element);

ListElmt *list_next(const ListElmt *element);
#endif

这里是list.c

#include <stdlib.h>
#include <string.h>
#include "List.h"

/* Need Help #1: The destroy function pointer is called here when the list is initialized and I need some explanation on how this works */

void list_init(List *list, void (*destroy)(void *data))
{

  list->size = 0;
  list->destroy = destroy;
  list->head = NULL;
  list->tail = NULL;

  return;
}

void list_destroy(List *list)
{

  void *data;

  while (list_size(list) > 0)
  {

    if (list_rem_next(list, NULL, (void **) &data) == 0&& list->destroy != NULL)
    {

      list->destroy(data);

      /* Need Help #2: The above line - how this works. I have no idea how this works because I haven't seen any code like that before. Also kindly let me know if this is recursion or not.*/
    }
  }
  memset(list, 0, sizeof(List));
  return;
}

int list_ins_next(List *list, ListElmt *element, const void *data)
{

  ListElmt *new_element;

  if ((new_element = (ListElmt *) malloc(sizeof(ListElmt))) == NULL ) // not yet understanded
    return -1;

  new_element->data = (void *) data;

  if (element == NULL )
  {
    if (list_size(list) == 0)
      list->tail = new_element;

    new_element->next = list->head;
    list->head = new_element;
  }

  else
  {
    if (element->next == NULL )
      list->tail = new_element;

    new_element->next = element->next;
    element->next = new_element;
  }

  list->size++;
  return 0;
}

int list_rem_next(List *list, ListElmt *element, void **data)
{

  ListElmt *old_element;

  if (list_size(list) == 0)
    return -1;

  if (element == NULL )
  { // Handle removal of the head

    *data = list->head->data;
    old_element = list->head;
    list->head = list->head->next;

    if (list_size(list) == 1)
      list->tail = NULL;
  }

  else
  { // Handle removal from somewhere else

    if (element->next == NULL )
      return -1;

    *data = element->next->data;
    old_element = element->next;
    element->next = element->next->next;

    if (element->next == NULL )
      list->tail = element;
  }

  free(old_element);

  list->size--;
  return 0;
}

2 个答案:

答案 0 :(得分:3)

问题#1

创建时传递给链接列表的参数destroypointer to a function。链接不知道如何销毁它所拥有的对象,从而释放内存。所以它需要来自外部的东西才能执行该操作。因此,用户必须编写一个知道如何释放保存在列表中的对象内存的函数,并告诉链表在需要销毁节点时使用该函数。

指向函数的指针保存在列表变量destroy中。

问题#2

您传递指针的函数刚刚被调用,并且正在传递指向当前节点中存储的数据的指针,以释放它占用的内存。

这种技术被称为command or action pattern(它不仅限于oop!)

答案 1 :(得分:0)

  • #help1:=没有任何东西被调用;在赋值list->destroy包含destroy函数的地址后,函数指针仅分配给:。
  • #help2:=现在调用该函数:func(arg)是一个函数调用,funcptr(arg)fncptr,如果memset(list, 0, sizeof(List));是指向函数类型的指针
  • #help3:= NULL错误地假设NULL指针值由全零表示。它不一定是。 (在大多数情况下,它是,但架构可能具有{{1}})
  • 的不同表示