Malloc of arrays and structs within a struct

后端 未结 5 1130
无人共我
无人共我 2021-02-14 12:09

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 i

相关标签:
5条回答
  • 2021-02-14 12:55
    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);
    }
    
    0 讨论(0)
  • 2021-02-14 12:57

    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);
    }
    
    0 讨论(0)
  • 2021-02-14 12:58

    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.

    0 讨论(0)
  • 2021-02-14 13:00

    It's not very readable but sometimes people create a structure with a count member and a final single-element array member. There then is a special factory method that allocates enough space so that you can write to count elements in the array. Obviously the array member can be of any type.

    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;
    }
    
    0 讨论(0)
  • 2021-02-14 13:04
    typedef struct _A { int i; } A;
    typedef struct _B { int j;  A a} B;
    

    To get a single B:

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

    To get an array of B:

    B *b = malloc(sizeof(B) * arrayLength);
    
    0 讨论(0)
提交回复
热议问题