【问题标题】:Making linked list more generic使链表更通用
【发布时间】:2016-10-01 14:44:22
【问题描述】:

谁能帮我理解使用链表的空指针。

我有:

struct listNode
{
    int nodeValue;
    struct listNode * next;
};

typedef struct listNode listNode;

仅适用于整数。如果我将 int nodeValue 更改为 void *nodeValue,我将如何使用 void 指针将值发送到我的链表中?

例如,我有一个添加到前面的功能:

void addFront(listNode *L, int number);

它接受一个 listNode 和一个数字。

如果它是一个 void* 指针,我是否只需将签名更改为:

void addFront(listNode *L, void* value);

在我使用整数的主函数中,我有类似的东西:

int main(void)
{   
    listNode *list;
    list = createList();

    for (int x = 0;x < 8;x++)
    {
        addFront(list,x);

    }

    return(0);
}

其中 createList 定义为:

listNode *createList()
{
    listNode *anyNode;
    anyNode = malloc(sizeof(listNode));
    anyNode->next = NULL;
    return anyNode;
}

listNode *initNode(int number)
{
    listNode *newNode;
    newNode = malloc(sizeof(listNode));
    newNode->nodeValue = number;
    newNode->next = NULL;
    return(newNode);
}

为了使列表更通用,我如何使用 void* 而不是声明整数来传递整数。

【问题讨论】:

    标签: c list generics dynamic dynamic-arrays


    【解决方案1】:

    不幸的是,这种通用行为是以大量开销为代价的:为了将int 保存在列表中,您需要通过动态分配int 来扩展其范围:

    listNode *initNode(int number)
    {
        listNode *newNode;
        newNode = malloc(sizeof(listNode));
        newNode->nodeValue = malloc(sizeof(int));
        *(newNode->nodeValue) = number;
        newNode->next = NULL;
        return(newNode);
    }
    

    这会多次增加内存需求,因为malloc(sizeof(int)); 通常会分配至少一个 16 字节的块。

    【讨论】:

      【解决方案2】:

      存储整数或指针的一种方法是将 nodeValue 设置为联合类型。请注意,为避免未定义的行为,您的调用代码需要保持一致(即,如果您将整数添加到链表中,则不应尝试稍后将它们作为指针访问,反之亦然)。

      union intOrPointer
      {
          int intValue;
          void * pointerValue;
      };
      
      struct listNode
      {
          union intOrPointer nodeValue;
          struct listNode * next;
      };
      
      typedef struct listNode listNode;
      
      listNode *initNode(int number)
      {
          listNode *newNode;
          newNode = malloc(sizeof(listNode));
          newNode->nodeValue.intValue = number;
          newNode->next = NULL;
          return(newNode);
      }
      

      【讨论】:

        【解决方案3】:

        另一种解决方案是在 listNode 声明中使用 0 大小的数组。 例如:

        #include <stdlib.h>
        #include <string.h>
        
        struct listNode
        {
          struct listNode *next;
          int nodeValue[0];
        };
        
        struct listNode *addFront(struct listNode **head, void *data, size_t size)
        {
          struct listNode *new_node = calloc(sizeof(struct listNode) + size, 1);
          if(!new_node)
            return NULL;
          new_node->next = *head;
          *head = new_node->next;
          memcpy(new_node->nodeValue, data, size);
        }
        
        void addInt2Front(struct listNode **head, int value)
        {
          addFront(head, &value, sizeof(value));
        }
        
        int main(void)
        {
          struct listNode *head = NULL;
          addInt2Front(&head, 5);
        }
        

        它减少了两次分配的开销,因为 nodeValue 的内存通过一次 calloc() 调用与 listNode 块一起分配。

        【讨论】:

        • 对不起,我的 addFront 需要返回 new_node。我忘了把它写成代码。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-03-28
        • 2012-06-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-07-04
        相关资源
        最近更新 更多