3. DATOS EN MEMORIA
Datos estáticos: Su tamaño y forma es constante durante la ejecución de un programa y
por tanto se determinan en tiempo de compilación. El ejemplo típico son los arrays.
Tienen el problema de que hay que dimensionar la estructura de antemano, lo que puede
conllevar desperdicio o falta de memoria.
Datos dinámicos: Su tamaño y forma es variable (o puede serlo) a lo largo de un
programa, por lo que se crean y destruyen en tiempo de ejecución. Esto permite
dimensionar la estructura de datos de una forma precisa: se va asignando memoria en
tiempo de ejecución según se va necesitando.
4. ASPECTOS A CONSIDERAR PARA EL USO DE MEMORIA DINAMICA
• En muchas ocasiones no es posible conocer de antemano la cantidad de variables
necesarias para un programa computacional.
• Existen aplicaciones que requieren de enormes cantidades de arreglos o datos por
momentos breves en el funcionamiento del mismo, por lo que no es viable declarar
de antemano a estas como variables, globales o locales de una función. Lo anterior
implica emplear funciones de ANSI C que permiten reservar memoria de manera
dinámica y ampliarla, reducirla o destruirla en tiempo de ejecución.
• El manejo de memoria dinámica es la base del poder del lenguaje C, C++ y le da la
capacidad de crear programas complejos que emplean grandes cantidades de
memoria y los maneja de manera eficiente.
5. Memoria dinámica
Es memoria que se reserva en tiempo de ejecución. Su principal ventaja frente a la estática, es que su tamaño
puede variar durante la ejecución del programa. (En C, el programador es encargado de liberar esta memoria
cuando no la utilice más). El uso de memoria dinámica es necesario cuando a priori no conocemos el número
de datos/elementos a tratar.
Cuando el sistema operativo carga un programa para ejecutarlo y lo convierte en proceso, le asigna cuatro
partes lógicas en memoria principal: texto, datos (estáticos), pila y una zona libre. Esta zona libre (o heap) es
la que va a contener los datos dinámicos, la cual, a su vez, en cada instante de la ejecución tendrá partes
asignadas a los mismos y partes libres que fragmentaran esta zona, siendo posible que se agote si no se
liberan las partes utilizadas ya inservibles. (La pila también varia su tamaño dinámicamente, pero la gestiona el
sistema operativo, no el programador):
6. • Las variables globales y del programa principal (main) se almacenan en posiciones
fijas de la memoria llamada memoria de datos.
• Las variables locales se almacenan en el segmento de memoria llamada pila y
existen solo cuando se hace una invocación a la función que las declaro. También se
pueden declarar variables estáticas locales que también se almacenan en
segmentos fijos de memoria o en la memoria de datos , sin embargo, también están
disponibles en la función que las declaro.
• Todas estas variables comparten una característica en común, se definen cuando se
compila el programa. Esto significa que el compilador reserva espacio en memoria
para almacenar los valores para estas variables.
• Sin embargo, no todas las veces es posible conocer el numero de variables con el
que va a constar nuestro programa. C C++ ofrece al desarrollador la opción de crear
diferentes tipos de variables de forma dinámica, para crear tales variables se utilizan
funciones como: malloc(), realloc(), calloc(), y free().
MEMORIA DINAMICA
7. • Las regiones de memoria que reservan/liberan estas funciones son almacenadas en el
montículo o heap.
MEMORIA DINAMICA
8. • Por lo regular cuando se diseña un algoritmo, se debe conocer que elementos de
entrada tendrá y cual será la salida, sin embargo, en algunas ocasiones no se sabe de
forma exacta el numero de variables que requerirá nuestro algoritmo.
• Por ejemplo, suponga que se van a registrar el numero de calificaciones de un conjunto
de alumnos, para resolver este problema se podría utilizar una arreglo de calificaciones,
sin embargo, si el numero de alumnos crece, nuestro programa ya no seria valido, puesto
que no existen los recursos necesarios para almacenar todos los datos validos.
Para resolver este problema es necesario recurrir al uso de apuntadores y a la asignación
dinámica de memoria.
ASIGNACION DINAMICA DE MEMORIA
9. ASIGNACION DINAMICA DE MEMORIA
El espacio de memoria asignado a una variable generada de manera
dinámica se crea durante la ejecución del programa (tiempo de ejecución),
al contrario de las variables declaradas en código, que el espacio de
memoria se les asigna en tiempo de compilación.
Una variable que es generada dinámicamente, se construye (por ejemplo
con malloc)y se puede destruir en tiempo de ejecución (uso de free).
17. Veamos un ejemplo en el cual el usuario ingresa una cantidad variable de números por consola. Primero el sistema le pide
que especifiqué la cantidad de números que va a ingresar, y luego de ingresados, los imprime, incrementando en 1 cada
número.
#include <stdio.h>
#include <stdlib.h>
int leercantidad();
void leer(int, int *);
void imprimir(int, int *);
main()
{
int cantidad,*ptr;
cantidad=leercantidad();
ptr=(int *)malloc(cantidad*sizeof(int));//reservo bloques de memoria
leer(cantidad,ptr);
imprimir(cantidad,ptr);
}
int leercantidad()
{
int n;
printf("Cuantos datos quiere ingresar:t");
scanf("%d",&n);
return n;
}
void leer(int n, int *ptr)
{
for(int i=0;i<n;i++)
{
printf("dato [%d]t",i+1);
//scanf("%d",&ptr[i]);
/*scanf("%d",ptr)
ptr++;*/ Mueve el puntero usando la aritmetica
scanf("%d",(ptr+i));//Mueve el puntero referenciado
}
}
void imprimir(int n, int *ptr)
{
for(int i=0;i<n;i++)
{
printf("dato [%d] %dn",i+1,*(ptr+i));
// ptr++;
}
}
18.
19.
20. Crear un programa que lea una línea de caracteres, reserva memoria para un
buffer de tantos caracteres como leídos y se copia en el buffer la cadena
ingresada:
Ejemplo
21. Crear un programa que cree un array de N valores de tipo entero de forma
dinámica
22. Ejemplo: Vector de tamaño dinámico
#include <stdio.h>
#include <stdlib.h>
float media (float v[], int n)
{
int i;
float suma = 0;
for (i=0; i<n; i++)
suma += v[i];
return suma/n;
}
main()
{
int i;
int n;
float *v;
printf("Número de elementos del vector: ");
scanf("%d",&n);
// Creación del vector
v = malloc(n*sizeof(float));
// Manejo del vector
for (i=0; i<n; i++)
v[i] = i;
printf("Media = %fn", media(v,n));
// Liberación de memoria
free(v);
}
27. Matrices Dinámicas
Realice un programa que genere una matriz de n filas y n columnas, muestre el resultado utilizando el formato de array
y el de puntero:
28. Practica
UTILIZANDO MEMORIA DINAMICA REALICE EL SIGUIETE EJERCICIO
MENU
1 DIAGONAL PRINCIPAL
2 DIAGONAL SECUNDARIA
3 COMBINAR DIAGONALES
4 SALIR
CREAR LAS FUNCIONES
LLENAR
DIAGONAL_PRINCIPAL
DIAGONAL_SECUNDARIA
COMBINAR_DPDS
29.
30.
31.
32.
33. - void *malloc(size_t size);
- void *calloc(size_t nmemb, size_t size);
malloc() Con esta función obtenemos el puntero que nos da la dirección del bloque de memoria reservado
dinámicamente. Sin embargo, malloc() no inicializa el contenido de este bloque de memoria.
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.
Se puede 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".
34.
35.
36.
37.
38.
39. 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.
40. void *realloc(void *p, size_t size) realloc cambia el tamaño del objeto al que apunta p y lo hace de tamaño
size. El contenido de la memoria no cambiará en las posiciones ya ocupadas. Si el nuevo tamaño es mayor
que el antiguo, no se inicializan a ningún valor las nuevas posiciones. En el caso en que no hubiese
suficiente memoria para “realojar” al nuevo puntero, se devuelve NULL y p no varía. El puntero que se pasa
como argumento ha de ser NULL o bien un puntero devuelto por malloc(), calloc() o realloc().
#define N 10
#include <stdio.h>
main(){
char c, *cambiante;
int i;
i=0;
cambiante = NULL;
printf("nIntroduce una frase. Terminada en [ENTER]n");
while ((c=getchar()) != 'n') {
if (i % N == 0){
printf("nLlego a %d posiciones y pido hasta %d", i, i+N);
cambiante=(char *)realloc((char *)cambiante,(i+N)*sizeof(char));
if (cambiante == NULL) exit(-1);
}
/* Ya existe suficiente memoria para el siguiente carácter*/
cambiante[i++] = c;
}
REALLOC