结构中的数组和结构的 Malloc

Posted

技术标签:

【中文标题】结构中的数组和结构的 Malloc【英文标题】:Malloc of arrays and structs within a struct 【发布时间】:2011-07-24 20:36:19 【问题描述】:

如何分配位于另一个结构中的结构?

我还想在一个结构中 malloc 一个项目数组,然后在需要时重新分配这个数组,这是如何正确完成的?

你能举一个声明结构然后上面的例子吗?

我有点不确定事情的顺序。

是否会释放结构中的数组,然后释放结构本身,是否必须在创建结构时分配结构,然后分配/声明其字段等?

【问题讨论】:

【参考方案1】:

包含在另一个struct 中的struct 包含在副本中,因此您不必单独对其进行malloc。如果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 函数只进行浅拷贝,即拷贝指针值,而不拷贝指向的对象。还有一次,你如何处理它取决于你的应用程序。

【讨论】:

谢谢。我想在结构内有一个动态数组。那么如果 struct Point2D 出于某种原因有一个数组,然后我们在一个 rect 结构中创建一个 Point2D,这是怎么做的呢?【参考方案2】:
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);

【讨论】:

【参考方案3】:

以下是结构体中嵌套结构体和数组的示例。在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);

【讨论】:

【参考方案4】:

它的可读性不是很强,但有时人们会创建一个包含一个计数成员和一个最终单元素数组成员的结构。然后有一个特殊的工厂方法,它分配足够的空间,以便您可以写入以计算数组中的元素。显然数组成员可以是任何类型。

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;

【讨论】:

【参考方案5】:
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);

【讨论】:

以上是关于结构中的数组和结构的 Malloc的主要内容,如果未能解决你的问题,请参考以下文章

结构体数组与用malloc申请结构体空间的对比

尝试 malloc 结构数组,但堆缓冲区溢出

如何使用 malloc 动态声明结构中存在的数组

malloc 用于 C 中的结构和指针

malloc分配内存的结构

数据结构与算法基础之malloc()动态分配内存概述