Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Malloc of arrays and structs within a struct

How does one malloc a struct which is inside another struct?

I would also like to malloc an array of items inside a struct and then realloc this array when needed, how is this done correctly?

Could you please give an example of declaring a struct and then the above.

Im a little unsure of the order of things.

Would the array within a struct be freed and then the struct itself, must the struct be malloced when it is created and then its fields be malloced/declared etc?

like image 382
some_id Avatar asked Mar 28 '11 22:03

some_id


People also ask

Do you need to malloc a struct inside a struct?

A struct included inside another struct is contained by copy, so you would not have to separately malloc it. If the struct contains a pointer to another struct , then you can consider allocating memory for it dynamically.

Can you malloc inside a struct?

The malloc() function is used for the declaration of the dynamic memory. An array of a struct can be declared either using the static memory or dynamic memory, in this write-up, we will discuss the array of structs using the malloc() function.

How do you allocate an array of structs?

There is another way to make an array of struct in C. The memory can be allocated using the malloc() function for an array of struct . This is called dynamic memory allocation. The malloc() (memory allocation) function is used to dynamically allocate a single block of memory with the specified size.

Can arrays be part of a struct?

A structure may contain elements of different data types – int, char, float, double, etc. It may also contain an array as its member. Such an array is called an array within a structure. An array within a structure is a member of the structure and can be accessed just as we access other elements of the structure.


2 Answers

The following is an example of nested structs and arrays in structs. You'll notice how the nested elements must be taken care of before you free the outer struct or else you'll end up with a memory leak.

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);
}
like image 141
Tim Cooper Avatar answered Nov 04 '22 22:11

Tim Cooper


A struct included inside another struct is contained by copy, so you would not have to separately malloc it. If the struct contains a pointer to another struct, then you can consider allocating memory for it dynamically.

struct Point2d
{
    float x;
    float y;
};

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

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

In struct Rect, the struct Point2D element are inserted into struct Rect and you don't have to dynamically allocate memory for them. On the contrary in the struct LinkedListNode the next element is referenced by a pointer and the memory must be dynamically allocated.

The two version are both useful, depending on the situation. There is no correct way to manage memory, it'll depend on your usage.

This same situation occurs in the case of an array. If your array is statically sized, then it can be directly included in the struct. However, if the size can vary, you must store a pointer within the 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;
}

The realloc function only does a shallow copy, that is pointer value is copied, but not the pointed object. One more time, how you deal with it will depend on your application.

like image 40
Sylvain Defresne Avatar answered Nov 04 '22 21:11

Sylvain Defresne