Variables dinámicas en C

Hasta ahora teníamos una serie de variables que declaramos al principio del programa o de cada función. Estas variables que reciben el nombre deestáticas, tienen un tamaño asignado desde el momento en que se crea el programa.

Pensemos en la “programación de una agenda”: tenemos una serie de fichas y nos interesa añadir más. Si pensamos en variables estáticas, prepararíamos la agenda para 1000 fichas aunque creamos que no vamos a pasar de 300. Está claro que esto es desperdiciar memória.

El uso de variables dinámicas se basa en reservar un poco de memoria para cada nuevo elemento que nos haga falta y enlazarlo a los que ya teníamos. Cuando queramos borrar un elemento, enlazamos el anterior a él con el posterior a él y liberamos la memoria que estaba ocupando.

Así que para seguir, necesitamos saber cómo reservar memoria y cómo liberarla.

Y entre otras cosas necesitamos “los punteros”….

Recordemos:

int num;  // “num” es un número entero

int *pos;    // “pos” es un puntero a entero = dirección de memoria en la que podemos guardar // un entero.
num=1;     // ahora “num” vale 1
pos=1000;         // “pos” ahora es la dirección 1000. Es peligroso ya que en la dirección de memoria // que contiene “pos” no sabemoa lo que hay y podemos provocar una catástrofe.
*pos=25;     // en la dirección de memoria de “pos” guardamos un 25 pos=#       // la variable “pos” contiene la dirección de memoria de la variable “num”.

En la práctica “pedimos” al compilador que nos reserve un poco de memoria donde él crea adecuado, utilizando la función “malloc”, que se encuentra en el fichero stdlib.h

Una vez hemos utilizado esta memoria es conveniente liberarla, utilizando la función “free”

Veamos:

– Prog111

/* Prog111.cpp */

#include <stdio.h>
#include <stdlib.h>
int num; int *pos;
void main()
{
printf(«num vale: %d (arbitrario)n»,num);
printf(«La dirección pos es: %p (arbitrario)n»,pos); num=1;
printf(«num vale: %d (fijado)n»,num);
pos=(int *) malloc(sizeof(int)); /* reservamos espacio */
printf(«La dirección pos es: %p (asignado)n»,pos);
printf(«El contenido de pos es: %d (arbitrario)n»,*pos); *pos=25; printf(«El contenido de pos es: %d (fijado)n»,*pos); free(pos);
pos=&num;
printf(«Y ahora el contenido de pos es: %d (valor de num)n»,*pos);
}

free(pos);
libera la memoria que ocupaba “pos”.
pos=(int *) malloc(sizeof(int));
sizeof(int): espacio a reservar, como el tamaño debe corresponder a un entero. sizeof(int) corresponde al tamaño de un entero.
“malloc” nos devuelve un puntero sin tipo (void *), como queremos guardar un dato entero, hemos de hacer una conversión de tipos: de “puntero sin tipo (void *)” a “puntero a entero (int *)”.

Una vez ejecutado el programa, observemos:

x Inicialmente “num” vale 0 (no podemos fiarnos de que siempre sea así, ya que no lo hemos inicializado nosotros)
x Inicialmente “pos” es 0. Es un puntero nulo, para el cual no se ha asignado un espacio en memoria.

– Prog112

/* Prog112.cpp */

/* Creación de un array dinámicamente */

#include <stdio.h>
#include <stdlib.h>
int *num;  /* puntero a numero entero */
int *temporal; /* temporal, para recorrer el array */
int i; /* para bucles */
void main()
{
/* Reservamos espacio para 10 números (array dinámico)
*/ num=(int *) malloc(10*sizeof(int));

for(i=0;i<10;i++) /* Recorremos el array */
num[i]=i*2; /* Dando valores */
printf(«La dirección de comienzo del array es: %pn»,num);
printf(«Valores del array: «);
for(i=0;i<10;i++) /* Recorremos el array */
printf(» %d «,num[i]); /* mostrando los valores */
printf(«n Valores del array (como puntero): «);
temporal=num;
for(i=0;i<10;i++) /* Recorremos como puntero */
printf(» %d «,*temporal++); /* mostrando los valores y
aumentando */ free(num); /* Liberamos lo reservado */
}

Como se ve, en “C” hay muy poca diferencia entre arrays y punteros: hemos declarado “num” como un puntero, pero hemos reservado espacio para más de un dato, y hemos podido recorrerlo como si hubiésemos definido: int num[10];

Fuente: Programación en C/C++ (Manual FV) de Fermí Vilà