martes, 12 de febrero de 2013

Localidad de Memoria/Palabras Reservadas


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 (== 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.

1 comentario: