2011-03-28 15 views
8

¿Cómo funciona una estructura malloc que está dentro de otra estructura?Malloc de matrices y estructuras dentro de una estructura

También me gustaría malloc una matriz de elementos dentro de una estructura y luego volver a colocar esta matriz cuando sea necesario, ¿cómo se hace esto correctamente?

Podría dar un ejemplo de cómo declarar una estructura y luego lo anterior.

Estoy un poco inseguro del orden de las cosas.

¿Se liberaría la matriz dentro de una estructura y luego la propia estructura, debe la estructura ser malloced cuando se crea y luego sus campos estar malloced/declarados, etc.?

Respuesta

8

Un struct incluido dentro de otro struct es contenida por copia, por lo que no tendría que malloc separado él. Si el struct contiene un puntero a otro struct, entonces puede considerar asignarle memoria dinámicamente.

struct Point2d 
{ 
    float x; 
    float y; 
}; 

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

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

En struct Rect, el elemento struct Point2D se insertan en struct Rect y usted no tiene que asignar dinámicamente la memoria para ellos. Por el contrario, en el struct LinkedListNode, el puntero hace referencia al siguiente elemento y la memoria debe asignárseme dinámicamente.

Las dos versiones son útiles, dependiendo de la situación. No hay una forma correcta de administrar la memoria, dependerá de su uso.

En el caso de una matriz, esta es la misma situación, ya sea que su matriz tenga un tamaño estático, y luego se puede incluir directamente en struct o su tamaño puede variar, en cuyo caso tendrá que almacenar en el puntero en el 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; 
} 

La función realloc sólo se hace una copia superficial, es decir, se copia el valor del puntero, pero no el objeto puntiagudo. Una vez más, la forma de lidiar con esto dependerá de su aplicación.

+0

Gracias. Quiero tener una matriz dinámica dentro de una estructura.Entonces, ¿qué pasa si struct Point2D tiene una matriz por alguna razón y luego creamos un Point2D dentro de una estructura rect, ¿cómo se hace esto? – jarryd

1
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); 
} 
1

El siguiente es un ejemplo de estructuras anidadas y matrices en estructuras. Notarás cómo deben cuidarse los elementos anidados antes de free la estructura externa o de lo contrario terminarás con una pérdida de memoria.

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
typedef struct _A { int i; } A; 
typedef struct _B { int j; A a} B; 

Para obtener una sola B:

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

para obtener una variedad de B:

B *b = malloc(size(b) * arrayLength); 
1

No es muy fácil de leer, pero a veces la gente a crear una estructura con un recuento miembro y un miembro de matriz de elemento único final. A continuación, existe un método de fábrica especial que asigna suficiente espacio para que pueda escribir para contar elementos en la matriz. Obviamente, el miembro de la matriz puede ser de cualquier tipo.

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; 
} 
Cuestiones relacionadas