INTRODUCCIÓN
Todos los objetos tienen un tiempo de vida, es decir, el
tiempo durante el cual se garantiza que el objeto exista. En C, existen 3 tipos
de duración: estática, automática y asignada. Las variables globales y las
variables locales declaradas con el especificador static tienen duración
estática. Se crean antes de que el programa inicie su ejecución y se destruyen
cuando el programa termina. Las variables locales no static tienen duración
automática. Se crean al entrar al bloque en el que fueron declaradas y se
destruyen al salir de ese bloque. Duración asignada se refiere a los objetos
cuya memoria se reserva de forma dinámica. Como se explicó anteriormente, esta
memoria se crea y se debe liberar de forma explícita. Los arreglos de longitud
variable de C99 son un caso especial. Tienen duración automática, con la
particularidad de que son creados a partir de su declaración.
La biblioteca estándar de C proporciona las funciones
malloc, calloc, realloc y free para el manejo de memoria dinámica. Estas
funciones están definidas en el archivo de cabecera stdlib.h.
MANEJO DE MEMORIA DEL LENGUAJE C
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; sin embargo
es algo más lento, pues es en tiempo de ejecución cuando se determina la
memoria a usar. En contrapartida la memoria estática es más rápida ya que está
disponible desde que se inició el programa.
Es el espacio en memoria que se crea al declarar variables
de cualquier tipo de dato (primitivas [int,char...] o derivados
[struct,matrices,punteros...]). Este tipo de memoria no puede cambiarse una vez
es declarada, y tampoco liberarse cuando ya no es necesaria, consumiendo de
esta forma recursos innecesariamente.
La
función
malloc
reserva
un bloque de memoria y devuelve un puntero void al inicio de la misma. Tiene la
siguiente definición:void *malloc(size_t size);
donde
el parámetro
size
especifica
el número de bytes a reservar. En caso de que no se pueda realizar la
asignación, devuelve el valor nulo (definido en la macro NULL
),
lo que permite saber si hubo errores en la asignación de memoria.
Ej:
int *puntero;
char *puntcarc;
puntero=(int *)malloc(4);
puntcarc=(char *)malloc(200);
A continuación se muestra
un ejemplo de su uso:
int *i;
…
/* Reservamos la memoria suficiente para almacenar un int y asignamos su dirección a i */
i = malloc(sizeof(int));
/* Verificamos que la asignación se haya realizado correctamente */
if (i == NULL) {
/* Error al intentar reservar memoria */
}
Uno de los usos más
comunes de la memoria dinámica es la creación de vectores cuyo número de
elementos se define en tiempo de ejecución:
int *vect1, n;
printf("N£mero de elementos del vector: ");
scanf("%d", &n);
/* Reservar memoria para almacenar n enteros */
vect1 = malloc(n * sizeof(int));
/* Verificamos que la asignación se haya realizado correctamente */
if (vect1 == NULL) {
/* Error al intentar reservar memoria */
}
La función
calloc
funciona de modo similar a malloc
,
pero además de reservar memoria, inicializa a 0 la memoria reservada. Se usa
comúnmente para arreglos y matrices. Está definida de esta forma:void *calloc(size_t nmemb, size_t
size);
El parámetro
nmemb
indica el número de
elementos a reservar, y size
el
tamaño de cada elemento. El ejemplo anterior se podría reescribir con calloc de
esta forma:int *vect1, n;
printf("N£mero de elementos del vector: ");
scanf("%d", &n);
/* Reservar memoria para almacenar n enteros */
vect1 = calloc(n, sizeof(int));
/* Verificamos que la asignación se haya realizado correctamente */
if (vect1 == NULL) {
/* Error al intentar reservar memoria */
}
La
función realloc redimensiona el espacio asignado de forma dinámica
anteriormente a un puntero. Tiene la siguiente definición:
void *realloc(void *ptr, size_t
size);
Donde
ptr
es el puntero a
redimensionar, y size
el
nuevo tamaño, en bytes, que tendrá. Si el puntero que se le pasa tiene el valor
nulo, esta función actúa como malloc
. Si la reasignación no se pudo
hacer con éxito, devuelve un puntero nulo, dejando intacto el puntero que se
pasa por parámetro. Al usar realloc
, se debería usar un puntero
temporal. De lo contrario, podríamos tener una fuga de memoria, si es que
ocurriera un error en realloc
.
Ejemplo
de
realloc
usando
puntero temporal:/* Reservamos 5 bytes */
void *ptr = malloc(5);
…
/* Redimensionamos el puntero (a 10 bytes) y lo asignamos a un puntero temporal */
void *tmp_ptr = realloc(ptr, 10);
if (tmp_ptr == NULL) {
/* Error: tomar medidas necesarias */
}
else {
/* Reasignación exitosa. Asignar memoria a ptr */
ptr = tmp_ptr;
}
Cuando se redimension la
memoria con
realloc
, si el nuevo tamaño (parámetro size
)
es mayor que el anterior, se conservan todos los valores originales, quedando
los bytes restantes sin inicializar. Si el nuevo tamaño es menor, se conservan
los valores de los primeros size
bytes.
Los restantes también se dejan intactos, pero no son parte del bloque regresado
por la función.
La
función
free
sirve
para liberar memoria que se asignó dinámicamente. Si el puntero es nulo, free
no hace nada. Tiene la
siguiente definición:void free(void *ptr);
El
parámetro
ptr
es
el puntero a la memoria que se desea liberar:int *i;
i = malloc(sizeof(int));
…
free(i);
Una
vez liberada la memoria, si se quiere volver a utilizar el puntero, primero se
debe reservar nueva memoria con
malloc
o calloc
:int *i = malloc(sizeof(int));
…
free(i);
/* Reutilizamos i, ahora para reservar memoria para dos enteros */
i = malloc(2 * sizeof(int));
…
/* Volvemos a liberar la memoria cuando ya no la necesitamos */
free(i);
Es usual usar la función sizeof() para indicar el número de
bytes, por ejemplo:
int *ip;
ip = (int
*) malloc(100 * sizeof(int) );
El compilador de C requiere hacer una conversión del tipo.
La forma de lograr la coerción (cast) es usando (char *) y (int *), que permite
convertir un apuntador void a un apuntador tipo char e int respectivamente.
Hacer la conversión al tipo de apuntador correcto asegura
que la aritmética con el apuntador funcionara de forma correcta. Es una buena
práctica usar sizeof() aun si se conoce el tamaño actual del dato que se
requiere, | ya que de esta forma el código se hace independiente del
dispositivo (portabilidad).
La función sizeof() puede ser usada para encontrar el
tamaño~ de cualquier tipo de dato, variable o estructura.
Simplemente se debe proporcionar uno de los anteriores como
argumento a la función.
Por lo tanto:
int i;
struct
COORD {float x,y,z};
struct
COORD *pt;
sizeof(int),
sizeof(i), sizeof(struct COORD) y
sizeof(PT) son también sentencias correctas.
PALABRAS RESERVADAS
El lenguaje de programación C se reserva el uso de algunas
palabras como identificadores internos clave para sus tipos de datos,
estructuras de control, sus instrucciones y otras funciones y características
propias del lenguaje. Por esta razón no es posible usarlos como identificadores
de variables, de funciones o de cualquier otro objeto. Los editores de texto
modernos las resaltan automáticamente para hacer los programas más legibles. A
continuación una lista de dichas palabras.
auto
|
doble
|
int
|
struct
|
break
|
else
|
long
|
switch
|
case
|
enum
|
register
|
typedef
|
char
|
extern
|
return
|
union
|
const
|
float
|
short
|
unsigned
|
continue
|
for
|
signed
|
void
|
default
|
goto
|
sizeof
|
volatile
|
do
|
if
|
static
|
while
|
Tabla 1 Palabras
reservadas
CONCLUSIONES
El manejo de memoria en el lenguaje c consiste en conseguir
o asignar espacio en memoria para dar más eficiencia y técnicamente hacer lo
que se requiera con dicho espacio asignado en memoria.
Existen dos tipos de asignación de memoria: estática y
dinámica. La memoria estática se crea al declarar variables y no puede ser
modificada ni liberarse una vez declarada mientras que la memoria dinámica se
reserva en tiempo de ejecución. Para el manejo de memoria dinámica se utilizan
las funciones malloc, calloc, realloc y free.
La función malloc reserva un bloque de memoria y devuelve un
apuntador de tipo void el cual es el inicio en memoria del bloque reservado de
tamaño especificado en el parámetro size. Al terminar de usar el bloque de
memoria reservado de debe liberar con la función free, de esta forma se evita
el consumo de memoria innecesaria, además de que permitirá que la memoria
liberada esté disponible para se usada nuevamente.
La función calloc inicializa la memoria reservada a cero y
la función realloc redimensiona el bloque de memoria ya asignado.
En todos los lenguajes de programación se usan palabras
reservadas, que son identificadores predefinidos para sus tipos de datos,
estructuras del control, entre otras instrucciones propias del lenguaje de programación.
tenkiu <3
ResponderEliminar