Маллок массивов и структур внутри структуры - PullRequest
8 голосов
/ 29 марта 2011

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

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

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

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

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

Ответы [ 5 ]

8 голосов
/ 29 марта 2011

A 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 делает только поверхностную копию, то есть копируется значение указателя, но не указательобъект.Еще раз, как вы справитесь с этим, будет зависеть от вашей заявки.

1 голос
/ 29 марта 2011

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

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;
}
1 голос
/ 29 марта 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);
1 голос
/ 29 марта 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);
}
1 голос
/ 29 марта 2011
typedef struct _A
{
  int *arr;
  int arrCount;
} A;

void Construct_A(A *a, int arraySize)
{
  a->arrCount = arraySize;
  a->arr = (int*)malloc(sizeof(int)*arraySize);
}

void Destruct_A(A *a)
{
  free(a->arr);
  a->arr = 0;
}

typedef struct _B
{
  A *a;
} B;

void Construct_B(B *b, int arraySize_A)
{
  b->a = (A*)malloc(sizeof(A));
  Construct_A(b->a);
}

void Destruct_B(B *b)
{
  Destruct_A(b->a);
  free(b->a);
  b->a = 0;
}

void main()
{
  B b;
  Construct_B(&b, 10);

  // Use b and b->a

  Destruct_B(&b);
}
...