domingo, 23 de febrero de 2014

Asignación de Memoria Dinámica y Estática

Asignación dinámica de memoria

La creación y mantenimiento de estructuras dinámicas de datos, requiere la asignación dinámica de memoria ya que es la capacidad del programa para obtener, en tiempo de ejecución, mas espacio de memoria para contener nuevos nodos, y poder liberar espacio ya no requerido. El limite de la asignación dinámica de memoria puede ser tan grande como la totalidad de memoria física disponible en la computadora, o la cantidad de memoria virtual disponible.

En C y C++ las funciones malloc y free así como el operador sizeof son esenciales para a asignación de memoria dinámica

Para que se puedan aplicar todas las funciones se estudiaran con estructuras autoreferenciadas estas son las que contienen un apuntador que apunta a una estructura del mismo tipo de estructura.

Ejemplo:


struct node 

                  {
                    int data;
                    struct node *nextPtr;
                  };


Una estructura anterior tiene dos miembros: el miembro entero data y el miembro apuntador nextPtr. El miembro nextPtr apunta a una estructura de tipo struct node ( es una estructura igual que la que se esta declarando). El apuntador se  conoce como vinculo o enlace, es decir, que enlaza las estructuras del mismo tipo.


Estructuras de nodo 

En la imagen anterior se puede mostrar dos nodos en donde el numero 2 esta señalando al numero 1 y este ultimo esta señalando a un dato NULL este valor es el encargado del termino de la estructura. 

Función malloc:

Toma como argumento el numero de bytes a asignarse, y regresa un apuntador del tipo void* a la memoria asignada. Un apuntador puede asignarse a una variable de cualquier tipo de apuntador.normalmente la funcion malloc se utiliza conjuntamente con el operador sizeof. 

Ejemplo:

 newPtr = malloc (sizeof (struct node) );

sizeof (struct node) evalúa el determinado tamaño en bytes para la una estructura, por lo tanto toda la función asigna un espacio de memoria en una nueva área del tamaño de sizeof (struct node) bytes, y lo almacena en la variable newPtr. Si no es disponible malloc regresa un apuntador NULL.


Función free: 


Esta función cancela la asignación de la memoria , es decir, regresa la memoria al sistema, de tal manera que en el futuro esta pueda ser asignada. Para  liberar memoria asignada dinámicamente mediante la función malloc.


Ejemplo:


free (newPtr);


Programa con la funcion malloc y free


#include <stdio.h> 
#include <stdlib.h> /* requerida para malloc y free funciones */ 
#include <iostream> 

using namespace std; 

int main() { 
int number; 
int *ptr; 
int i; 

printf("Cuantos números enteros desea ingresar? "); 
scanf("%d", &number); 
//En algunos compiladores podrías usarlo así 
//ptr = malloc(number*sizeof(int)); /* Creamos el espacio de memoria en forma dinámica */ 
//Nosotros tenemos DEV C++ y tenemos que hacerlo así para que funcione. 
ptr = (int *)malloc(number*sizeof(int)); /* Creamos el espacio de memoria en forma dinámica */ 

if(ptr!=NULL) { 
for(i=0 ; i<number ; i++) { 
*(ptr+i) = i; 


for(i=number ; i>0 ; i--) { 
printf("%d\n", *(ptr+(i-1))); /* Imprimimos en orden inverso */ 
} 

free(ptr); /* Liberamos la memoria reservada */ 
system("PAUSE"); 
return 0; 

else { 
printf("\nLa reserva de memoria no suficiente memoria.\n"); 
return 1; 






Función calloc:
Esta se inicializa en la zona de memoria reservada. sus argumentos son diferentes de la función malloc que solo recibe el numero de bytes a reservas. Para calloc es necesario dar en el numero de elementos y el tamaño de cada uno de sus elementos.

void* calloc(size_t nmemb, size_t size);

Función realloc:
Esta cambia el tamaño de la memoria que se asigno dinamicamente copiando, su contenido anterior.

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


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

int main( void )
{
   int *numPtr, i;
   size_t tamanyo=0;

   printf( "Introduzca el tamaño de la lista: " );
   scanf( "%d", &tamanyo );

   puts( "Adjudicamos espacio a la lista (con calloc)." );
   numPtr = (int *)calloc( tamanyo, sizeof(int) );

   for( i=0; i<tamanyo-1; i++ )
      printf( "%d, ", numPtr[i] = rand() % 100 + 1 );
   printf( "%d\n", numPtr[i] = rand() % 100 + 1 );

   numPtr = (int *)realloc( numPtr, tamanyo/=2 );
   printf( "Recortamos la lista a la mitad: %d\n", tamanyo );
   for( i=0; i<tamanyo-1; i++ )
      printf( "%d, ", numPtr[i] );
   printf( "%d\n", numPtr[i] );

   puts( "Liberamos el espacio (con realloc)." );
   realloc( numPtr, 0 );    /* Una forma poco ortodoxa, pero válida, de liberar espacio */
   system("pause");
   return 0;

}


Asignación estática de memoria.

Esta consiste en el proceso de la asignación de memoria al tiempo que se compila el programa y antes que el programa sea ejecutado, a diferencia con la asignación dinámica  donde se asigna la memoria en el tiempo que el programa en ejecución lo necesita.

Una aplicación de esta técnica se lleva mediante modulo de programación, es decir, funciones o subrutinas declarando los datos de forma local, osea que desde otro modulo son inaccesibles excepto que se le pasen como parámetros o sean devueltos por la función.