C связанный список с динамическим размером узла - PullRequest
0 голосов
/ 25 февраля 2019

Я пытаюсь создать связанный список в C, где каждый узел имеет определенный размер, введенный пользователем при запуске программы.Я уже думал о структуре:

struct ListNode{

    char * str;

    struct ListNode * next_node;

};

, но здесь размер каждого узла фиксирован.Есть идеи?

Заранее большое спасибо.

Ответы [ 2 ]

0 голосов
/ 13 августа 2019

Звучит так, как будто вы ищете функцию «элемента гибкого массива», при которой неполный массив помещается в конец структуры:

struct ListNode {
  struct ListNode *next;
  char data[];
};

Это выделяется как:

struct ListNode *node = malloc(sizeof *node + data_size_bytes);

Тогда мы можем сохранить значения в node->data[i] для i от 0 до data_size_bytes - 1.Вся структура и данные находятся в одном линейном блоке.

Обратите внимание, что структура с гибким элементом не может использоваться в качестве типа элемента массива.

До добавления стандарта ISO C гибкийчлен массива в 1999 году, это было сделано как популярный "struct hack" с использованием массива размером 1. Если вы ограничены работой в C90, это выглядит так:

struct ListNode {
  struct ListNode *next;
  char data[1];
};

Теперь sizeof ListNode включаетмассив из одного элемента, и , вполне вероятно, заполнение для выравнивания.Например, в системе с четырьмя байтовыми указателями размер вполне вероятно равен восьми.Если мы используем одну и ту же строку malloc, мы выделим лишнюю память.Правильное malloc выражение, которое нужно использовать для взлома структуры C90:

#include <stddef.h>

struct ListNode *node = malloc(offsetof(struct ListNode, data) + data_size_bytes);

В отличие от функции члена гибкого массива, взлом структуры не имеет формально четко определенного поведения;это просто то, что «работает, если работает».

0 голосов
/ 25 февраля 2019

Кажется, вам нужен размер данных, который содержит узел, чтобы каждый раз изменяться.Вы можете достичь этого, используя узел постоянного размера, который содержит указатель на динамически размещаемые данные.

Обратите внимание, что в приведенном ниже примере размер структуры остается sizeof (void *) + sizeof (node ​​*), но размерданные, выделенные для каждого узла, изменяются с использованием пользовательского ввода.

typedef struct Dnode
{
    void* data;
    struct Dnode* next;
}Dnode;

Dnode* CreateDnode(size_t data_size_bytes)
{
    Dnode* newNode = NULL;

    newNode =  malloc(sizeof(Dnode));/*always the same*/
    if(NULL == newNode)
    {
        return NULL;
    }
    newNode->data =  malloc(data_size_bytes);/*changes by input*/
    if(NULL == newNode->data)
    {
        return NULL;
    }
    newNode->next = NULL;
    return newNode;
}
...