Malloc массивов и структур внутри структуры

Как можно выделить структуру, находящуюся внутри другой структуры?

Я также хотел бы выделить массив элементов внутри структуры, а затем при необходимости перераспределить этот массив, как это сделать правильно?

Не могли бы вы привести пример объявления структуры, а затем выше.

Я немного не уверен в порядке вещей.

Будет ли массив внутри структуры освобожден, а затем сама структура, должна ли структура быть распределена при ее создании, а затем ее поля будут распределены/объявлены и т. д.?


person some_id    schedule 28.03.2011    source источник


Ответы (4)


struct, включенный в другой struct, содержится в копии, поэтому вам не нужно отдельно выделять его. Если struct содержит указатель на другой struct, вы можете рассмотреть возможность динамического выделения памяти для него.

struct Point2d
{
    float x;
    float y;
};

struct Rect
{
    struct Point2D a;
    struct Point2D b;
};

struct LinkedListNode
{
    struct LinkedListNode* next;
    int value;
};

В struct Rect элементы struct Point2D вставляются в struct Rect и вам не нужно динамически выделять для них память. Напротив, в struct LinkedListNode на следующий элемент ссылается указатель, и память должна выделяться динамически.

Обе версии полезны в зависимости от ситуации. Не существует правильного способа управления памятью, это будет зависеть от вашего использования.

Такая же ситуация возникает и в случае с массивом. Если ваш массив имеет статический размер, то его можно напрямую включить в файл struct. Однако, если размер может варьироваться, вы должны сохранить указатель в файле struct.

struct Header
{
    char magic[4];
    unsigned int width;
    unsigned int height;
};

struct Buffer
{
    char* data;
    unsigned int size;
    unsigned int capacity;
};

struct Buffer* buffer_init()
{
    struct Buffer* buffer = (struct Buffer*)malloc(sizeof(struct Buffer));
    buffer->data = 0;
    buffer->size = 0;
    buffer->capacity = 0;
}

void buffer_grow(struct Buffer* buffer, size_t capacity)
{
    if (capacity > buffer->capacity)
    {
        buffer->data = realloc(buffer->data, capacity);
        buffer->capacity = capacity;
    }
}

void buffer_append(struct Buffer* buffer, const char* data, unsigned int dataLen)
{
    if (dataLen + buffer->size > buffer->capacity)
        buffer_grow(MAX(dataLen + buffer->size, buffer->capacity * 2));

    memcpy(buffer->data + buffer->size, data, dataLen);
    buffer->size += dataLen;
}

Функция realloc делает только поверхностную копию, то есть копируется значение указателя, но не указанный объект. Еще раз, как вы с этим справитесь, будет зависеть от вашего приложения.

person Sylvain Defresne    schedule 28.03.2011
comment
Спасибо. Я хочу иметь динамический массив внутри структуры. Так что, если структура Point2D по какой-то причине содержит массив, а затем мы создаем Point2D внутри структуры rect, как это сделать? - person some_id; 29.03.2011

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

typedef struct Base Base;
struct Base
{
  int x;
};

typedef struct Sample Sample;
struct Sample
{
  Base base;
  int size;
  int *arr;
};

// Create the sample struct

Sample *createSample()
{
  Sample sample = malloc(sizeof(Sample));
  if(sample == NULL)
  {
    return NULL;
  }
  sample->base = malloc(sizeof(Base));
  if(sample->base == NULL)
  {
    free(sample);
    return NULL;
  }
  sample->base->x = 0;
  sample->size = 0;
  sample->arr = NULL;
  return sample;
}

// Adding element to the array

void addItemToSample(Sample *sample, int item)
{
  if(sample == NULL)
  {
    return;
  }
  int *arr = realloc(sample->arr, sizeof(int) * (sample->size + 1));
  if(arr == NULL)
  {
    return;
  }
  arr[sample->size++] = item;
  sample->arr = arr;
}

// Freeing the struct

void freeSample(Sample *sample)
{
  // Free deep elements first
  free(sample->base);
  free(sample->arr);
  // Free outer
  free(sample);
}
person Tim Cooper    schedule 28.03.2011

Это не очень читабельно, но иногда люди создают структуру с членом-счетчиком и конечным членом-массивом из одного элемента. Затем существует специальный фабричный метод, который выделяет достаточно места, чтобы вы могли писать для подсчета элементов в массиве. Очевидно, что элемент массива может быть любого типа.

typedef struct {
    int count;
    int elements[1];
} int_array;

int_array* allocate_int_array(int count)
{
    int_array* mem = (int_array*)malloc(sizeof(int_array) + (count - 1) * sizeof(int));
    if (mem)
        mem->count = count;
    return mem;
}
person Neil    schedule 28.03.2011

typedef struct _A { int i; } A;
typedef struct _B { int j;  A a} B;

Чтобы получить одну букву B:

B *b = malloc(sizeof(B));

Чтобы получить массив B:

B *b = malloc(sizeof(B) * arrayLength);
person Richard Schneider    schedule 28.03.2011