2010-10-31 15 views
5

Estoy intentando añadir 10 elementos más a mi estructura que ya se ha malloc con un tamaño fijo de 20. Esta es la forma en que he definido mi estructura:¿Cómo asigno más espacio para mi matriz de estructuras C?

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

struct st_temp { 
    char *prod; 
}; 

int main() 
{ 
    struct st_temp **temp_struct; 

    size_t j; 
    temp_struct = malloc (sizeof *temp_struct * 20); 
    for (j = 0; j < 20; j++) { 
     temp_struct[j] = malloc (sizeof *temp_struct[j]); 
     temp_struct[j]->prod = "foo"; 
    } 

    return 0; 
} 

Así que lo que tenía en mente era a realloc como (sin embargo, no está seguro de cómo hacerlo):

temp_struct = (struct st_temp **) realloc (st_temp, 10 * sizeof(struct st_temp*)); 

y luego añadir los 10 elementos adicionales,

for (j = 0; j < 10; j++) 
     temp_struct[j]->prod = "some extra values"; 

¿Cómo podría lograr esto? ¡Cualquier ayuda es apreciada!

+0

Estoy de acuerdo con Daniel ... ¿Cuál es el motivo de la indirección de doble puntero? ¿No sería más simple tener 'struct st_temp * temp = malloc (20 * sizeof * temp); para (...) {temperatura [i] .prod = "foo"; } '?? La memoria que maneja menos manualmente, la solución es menos propensa a errores. –

Respuesta

5

Para evitar pérdidas de memoria, tenemos que manejar la reasignación con cuidado (más sobre esto más adelante) . La función realloc:

void *realloc(void *ptr, size_t size), donde

ptr = el puntero al bloque de memoria original (malloc 'ed), y

size = el nuevo tamaño del bloque de memoria (en bytes).

realloc devuelve la nueva ubicación del bloque de memoria asignado dinámicamente (que puede haber cambiado) - o NULL si la reasignación falló. Si devuelve NULL, la memoria original permanece sin cambios, por lo que siempre debe usar una variable temporal para el valor de retorno de realloc.

Un ejemplo aclarará esto un poco (puntos de interés: la sintaxis de Realloc es similar a la de Malloc (no necesita moldes adicionales, etc.) y, después de realloc, debe producir los mismos pasos para los nuevos objetos que después de malloc):

struct st_temp **temp_struct; 
temp_struct = malloc(20 * sizeof *temp_struct); 
if (temp_struct == NULL) { /* handle failed malloc */ } 
for (int i = 0; i < 20; ++i) { 
    temp_struct[i] = malloc(sizeof *temp_struct[i]); 
    temp_struct[i]->prod = "foo"; 
} 

// We need more space ... remember to use a temporary variable 
struct st_temp **tmp; 
tmp = realloc(temp_struct, 30 * sizeof *temp_struct); 
if (tmp == NULL) { 
    // handle failed realloc, temp_struct is unchanged 
} else { 
    // everything went ok, update the original pointer (temp_struct) 
    temp_struct = tmp; 
} 
for (int i = 20; i < 30; ++i) { // notice the indexing, [20..30) 
    // NOTICE: the realloc allocated more space for pointers 
    // we still need to allocate space for each new object 
    temp_struct[i] = malloc(sizeof *temp_struct[i]); 
    temp_struct[i]->prod = "bar"; 
} 
// temp_struct now "holds" 30 temp_struct objects 
// ... 
// and always do remember, in the end 
for (int i = 0; i < 30; ++i) 
    free(temp_struct[i]); 
free(temp_struct); 

Ten en cuenta, que esto no es realmente una gran variedad de estructuras, sino más bien un vector de punteros a estructuras - o incluso una matriz de matrices de estructura si lo desea. En el último caso, cada subarreglo sería de longitud 1 (ya que solo asignamos espacio para una estructura).

+0

Gracias. Buena información, ¿sabes por qué obtengo: asignación del tipo de puntero incompatible cuando temp_struct = tmp; ? – Josh

+0

Tuve un error tipográfico en la declaración de 'tmp'. –

8

Cuando utiliza realloc(), debe dar el nuevo tamaño en lugar de la cantidad de bytes para agregar. Entonces:

temp_struct = (struct st_temp **) realloc (temp_struct, 30 * sizeof(struct st_temp*)); 

30 es, por supuesto, su original 20 más 10 más. La función realloc() se encarga de copiar los datos originales a una nueva ubicación si es necesario mover el bloque de memoria.

A continuación, añadir los 10 elementos adicionales sería algo así como (empieza en el índice 20, no 0):

for (j = 20; j < 30; j++) { 
    temp_struct[j]->prod = "some extra values"; 
} 
+0

¡Gracias por la información! – Josh

+0

+1, simple y preciso – slezica

+0

¿Un poco demasiado simple, quizás? Duplicar el concepto erróneo original de no tener que asignar nuevos objetos (realloc no hace eso) y ningún manejo de errores (algo crucial en C). –

Cuestiones relacionadas