lunes, 31 de octubre de 2011

malloc vs calloc

Anteriormente en la segunda parte de punteros hablé acerca de cómo crear arrays dinámicos. Vimos la importancia de la función malloc() en este proceso. Sin embargo existen otras dos funciones complementarias a malloc(). Estas funciones son calloc() y realloc().

Para comenzar a ver las diferencias entre estas funciones veremos sus definiciones:
- void *malloc(size_t size);
- void *calloc(size_t nmemb, size_t size);
- void *realloc(void *ptr, size_t size);

Primero hablaré de las diferencias entre malloc y calloc. Vimos anteriormente que gracias a malloc() obteníamos el puntero que nos daba la dirección del bloque de memoria reservado dinámicamente. Sin embargo, malloc() no inicializa el contenido de este bloque de memoria. Por otra parte calloc() cumple la misma función que malloc(), con una diferencia: calloc() si inicializa a 0 el contenido de cada elemento del array dinámico. Podemos apreciar como en la definición de calloc() el primer parámetro es el nº de elementos y a continuación el tamaño del elemento (por ejemplo para int: sizeof(int)). Mientras que en malloc() debíamos pasarle el tamaño del bloque entero, es decir: "nºelementos*tamaño de elemento".
Nota: calloc() es computacionalmente algo más cara, sin embargo, a veces conviene usarla en lugar de malloc().

Por último veremos la función realloc(). Esta función posee una gran utilidad, pues es la que nos sirve para redimensionar nuestro bloque de memoria (array, etc) generado dinámicamente. Sus parámetros son: el puntero a redimensionar y el nuevo tamaño, que al igual que en malloc() será: "nº elementos*tamaño de elemento". Esta función guarda el contenido que tengamos almacenado en el bloque de memoria a redimensionar. En el caso de que lo hagamos mas pequeño elimina el contenido sobrante. En caso de que al redimensionar no exista espacio consecutivo para el nuevo bloque realloc() cambia de lugar nuestro bloque y nos devuelve el puntero a la nueva dirección. Es por esto por lo que siempre deberemos guardar el puntero obtenido con esta función. 

Ejemplos:
- Crear array de int dinámicamente de 100 posiciones:
    int *v;
  • v =  (int *) malloc(100 * sizeof(int));
  • v = (int *) calloc(100, sizeof(int));
- Redimensionar 'v' para que tenga 150 posiciones:
  • v = (int *) realloc(v, 150*sizeof(int));

Espero que esto os sirva de ayuda a la hora de trabajar con la memoria de forma dinámica.

10 comentarios:

  1. Gracias por la información, es muy útil (:

    ResponderEliminar
  2. Gracias! me sirvió mucho

    ResponderEliminar
  3. ¿Por lo tanto con calloc si reservo esapcio para un arry no tendría que incializar a 0 sus posiciones?

    ResponderEliminar
  4. hola... gracias por la explicacion... podrías hacer algo con listas simplemente encadenadas (o dobles) ?...

    ResponderEliminar
  5. Hola, de acuerdo a como funciona Realloc, cuando se redimensiona para un tamaño mas grande.. De que forma hace esa nueva asignación? como malloc o calloc? es decir, va a dejar el contenido inicializado en cero o no?

    ResponderEliminar
    Respuestas
    1. Hola, la verdad es que es una buena pregunta que no me había planteado. Sé que si realizas realloc pasando como argumento un puntero nulo, la función realloc actúa como malloc. En cuánto saque un poco de tiempo me gustaría poder hacer pruebas y contestarte. Aunque según la descripción de realloc, esta función simplemente mueve nuestro puntero y reserva memoria en función del tamaño especificado, no se dice nada de que deba inicializar a 0.

      De todas formas échale un vistazo a los motivos por los que no se debe hacer realloc: http://www.iso-9899.info/wiki/Why_not_realloc

      Eliminar
  6. He usaso malloc pero me sale q tengo q declararla
    uso el dev c++ Ayuda

    ResponderEliminar