INTRODUCCIÓN
Este es un lenguaje orientado
en la implementación de sistemas operativos como Unix. El lenguaje C es apreciado
por la eficiencia del código que produce y es el lenguaje de programación más
popular para crear software de sistemas, aunque también puede ser utilizado
para crear nuevas aplicaciones.
Un manejador
de memoria es un componente que te permite administrar de manera sencilla y
fiel los recursos que maneja tu programa (software), específicamente el recurso
de la memoria.
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
En los lenguajes informáticos, una palabra reservada es
una palabra que tiene un significado gramatical especial para ese lenguaje y no puede ser utilizada
como un identificador en ese lenguaje.
Manejo de memoria en el lenguaje C
Un manejador
de memoria es un componente que te permite administrar de manera sencilla y
fiel los recursos que maneja tu programa (software), específicamente el recurso
de la memoria.
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.
Como sabemos, en lenguaje C/C++ , &x es la
dirección donde se almacena en memoria la variable x. Si p es un apuntador en C/C++ , *p es el contenido de la localidad
de memoria p. Si usamos C/C++ para implementar listas ligadas, podemos usar estos apuntadores. Sin
embargo, primero analizaremos cómo asignar y liberar el almacenamiento en forma
dinámica y cómo se accesa al almacenamiento dinámico en C/C++ .
Malloc
En C/C++ , una
variable que debe contener la dirección en la memoria que almacena un número
entero se crea mediante la declaración
int *p;
Recordemos que esta declaración se divide en dos partes: la parte de
tipo int *, que indica
que se trata de un apuntador a un entero; y la parte de identificador, en este
caso p. Una vez declarada la variable p como un apuntador a un tipo específico de dato, debe ser posible crear
dinámicamente un objeto de este tipo específico y asignar su dirección a p. Esto se hace en C/C++ mediante la
función de la biblioteca estándar malloc (size). La función malloc asigna de
manera dinámica una parte de memoria de tamaño especificado en size y devuelve un apuntador a un elemento de tipo char. Consideremos las siguientes declaraciones:
extern char *malloc();
int *pi; float *pr;
La palabra clave extern especifica
que una variable o función tiene un enlace externo. Esto significa que la
variable o función a la que nos referimos está definida en algún otro archivo
fuente, o más adelante en el mismo archivo. Sin embargo, en
C/C++ podemos usar esta palabra clave extern con una cadena. La cadena indica que se está usando el convenio de
enlace de otro lenguaje para los identificadores que se están definiendo. Para
los programas C++ la cadena por defecto es ``C++''.
Los enunciados:
pi = (int *) malloc(sizeof(int));
pr = (float *) malloc(sizeof(float));
Crean directamente la variable entera *pi y la variable real *pr. Estas se
denominan variables dinámicas. Al ejecutar estos enunciados, el operador sizeof devuelve el tamaño en bytes de su operando. Esto se usa para conservar
la independencia de máquina. Después, malloc crea un objeto de este tamaño. Por tanto, malloc(sizeof(int)) asigna almacenamiento para un entero, en tanto que malloc(sizeof(float)) asigna espacio necesario para un real. De igual manera, malloc devuelve un apuntados al almacenamiento que asigna. Este apuntador es
al primer byte de este almacenamiento y es de tipo char
*. Para obligar al apuntador a que señale a un entero, usamos el operador
de cálculo (int *) ó (float
*).
El operador sizeof, devuelve
un valor de tipo int, en tanto que la función malloc espera un parámetro de tipo unsigned. Para hacer que correspondan, debemos escribir
pi=(int *)malloc((unsigned)(sizeof(int)));
Como ejemplo, vamos a considerar este breve código:
#include <iostream>
int main (int argc, char * const argv[]) {
( 1) int *p, *q;
( 2) int x;
( 3) p = (int
*)malloc(sizeof(int));
( 4) *p = 3;
( 5) q = p;
( 6) std::cout<< *p
<< " " << *q
<< "\n";
( 7) x = 7;
( 8) *q = x;
( 9) std::cout<< *p
<< " " << *q
<< "\n";
(10) p = (int
*)malloc(sizeof(int));
(11) *p = 5;
(12)
std::cout<< *p << "
" << *q << "\n";
return
0;}
En la línea (3), se crea una variable de tipo entero y su dirección se
coloca en p. La línea (4) establece el valor
de esa variable en 3. La línea (5) hace que la dirección q sea la misma dirección que p. El enunciado de la línea (5) es perfectamente válido, pues se asigna a
una variable de tipo apuntador (q) el valor de otra variable del mismo tipo
(p). En este momento *p y *q hacen referencia a la misma variable. Por tanto, la línea (6) imprime
el contenido de esa variable (que ahora es 3) dos veces.
En la línea (7), se almacena el valor 7 en la variable entera x. La línea (8) cambia el valor de *q al valor de x. sin embargo, dado que p y q apuntan a la misma variable, *p y *q tienen el valor 7. Por tanto la
línea (9) imprime el número 7 dos veces.
La línea (10) crea una nueva variable entera y coloca su dirección en p. Ahora *p hace referencia a la variable
entera recién creada que todavía no ha recibido un valor. q no ha cambiado; por lo que el valor de *q sigue siendo 7. Observemos que *p no hace referencia a una variable específica única. Su valor cambia
conforme se modifica el valor de p. La línea (11) establece el valor de esta variable recién creada en 5 y
la línea 12 imprime los valores 5 y 7. Y así la salida del programa es:
3 3
7
7
5 7
Malloc;
Ejemplo has exited with status 0.
La función free se usa en C
para liberar almacenamiento de una variable asignada dinámicamente.
La orden free(p);
invalida cualquier referencia futura a la variable *p (a menos que se asigne nuevo espacio de memoraia a esa variable).
Llamar free(p) hace que
quede disponible para reúso el almacenamiento ocupado por *p, si es necesario.
La función free espera un
parámetro apuntador del tipo char *, para que
no tengamos problemas de tipos, debemos hacer
free((char *)p);
Consideremos el siguiente ejemplo para ilustrar el uso de free:
#include <iostream>
int main (int argc, char * const argv[]) {
int *p, *q;
( 1) p=(int *)malloc(sizeof(int));
( 2) *p=5;
( 3) q=(int *)malloc(sizeof(int));
( 4) *q=8;
( 5) free(p);
( 6) p=q;
( 7) q=(int *)malloc(sizeof(int));
( 8) *q=6;
( 9) std::cout<<*p<<"
"<<*q<<"\n";
return 0;}
Punteros void
La función malloc devuelve un puntero inespecífico, que no apunta a un
tipo de datos determinado. En C, estos punteros sin tipo se declaran como void*
Muchas
funciones que devuelven direcciones de memoria utilizan los punteros void*. Un
puntero void* puede convertirse a cualquier otra clase de puntero:
char* ptr = (char*)malloc(1000);
El problema de malloc es conocer cuántos bytes se quieren reservar. Si se
quiere reservar una zona para diez enteros, habrá que multiplicar diez por el
tamaño de un entero.
El tamaño en bytes de un elemento
de tipo T se obtiene con
la expresión sizeof
(T)
Función free
Cuando una zona de memoria reservada con malloc ya no se necesita, puede ser liberada mediante la función free.
void free (void* ptr);
ptr es un puntero de cualquier tipo que apunta a un área de
memoria reservada previamente con malloc.
Si ptr apunta a una
zona de memoria indebida, los efectos pueden ser desastrosos, igual que si se
libera dos veces la misma zona.
CALLOC
La función CALLOC sirve para
obtener un bloque de memoria especificado en términos del número de elementos y
el tamaño de estos elementos
#include <stdlib.h>
void *calloc(size_t nelem, size_t elsize);
La función calloc inicializa todos
los elementos del bloque de memoria a cero
Ejemplo:
int *p = (int
*)calloc(100,sizeof(int))
REALLOC
La función REALLOC puede cambiar
el tamaño del bloque apuntado por un apuntador especifico
#include <stdlib.h>
void *realloc(void *ptr, size_t size);
El apuntador *ptr debe estar
apuntando hacia algún bloque de memoria. En caso de que el apuntador sea nulo
la función trabaja igual que malloc
Ejemplo
void leer(int *A, int n)
{
for(int i=0; i < n; i++ )
{
printf("A[%d] = ", i);
scanf("%d",&A[i]);
}
}
void imprime(int *A, int n)
{
for(int i=0; i < n; i++ )
printf("A[%d] = %d \n",
i,A[i]);
}Ejemplo
5
void leer(int *A, int n)
{
for(int i=0; i < n; i++ )
{
printf("A[%d] = ", i);
scanf("%d",&A[i]);
}
}
void imprime(int *A, int n)
{
for(int i=0; i < n; i++ )
printf("A[%d] = %d \n",
i,A[i]);
}
Método de Ordenamiento
void burbuja(int *A, int n)
{
int i,j,temp;
for(i = 0; i < (n-1); i++)
for(j = i+1; j < n; j++)
if (A[i] > A[j])
{
temp = A[i];
A[i] = A[j];
A[j] = temp;
}
}
Programa Principal
#include <stdio.h>
#include <stdlib.h>
void burbuja(int *A, int n);
void leer(int *A, int n);
void imprime(int *A, int n);
main()
{
int n, *A;
printf("Proporciona el numero de datos a leer:
");
scanf("%d",&n);
A = (int *)malloc(n*sizeof(int));
leer(A,n);
burbuja(A,n);
imprime(A,n);
system("pause");
return 0;
}
Palabras reservadas
En los lenguajes informáticos, una palabra reservada es una palabra que tiene un
significado gramatical especial para ese lenguaje y no puede ser utilizada
como un identificador en ese lenguaje.
Por ejemplo, en SQL, un usuario
no puede ser llamado "group", porque la palabra
group
es usada para indicar que un identificador se
refiere a un grupo, no a un usuario. Al tratarse de una palabra clave su uso
queda restringido.
Ocasionalmente la especificación de un lenguaje de programación puede
tener palabras reservadas que están previstas para un posible uso en futuras
versiones. En Java
const
y goto
son palabras reservadas — no tienen significado en
Java, pero tampoco pueden ser usadas como identificadores. Al reservar los
términos pueden ser implementados en futuras versiones de Java, si se desea,
sin que el código fuente más antiguo escrito en Java deje de funcionar.
En la CLI de .NET, todos los
lenguajes tienen que proporcionar un mecanismo para utilizar los
identificadores públicos que son palabras reservadas en ese lenguaje. Para ver
por qué es necesario, supongamos que se define una clase en VB.NET como sigue:
Public Class this
End Class
Entonces, se compila esta clase en un ensamblado de .NET y se distribuye como parte de un conjunto de
herramientas. Un programador de C#, que quiere
definir una variable de tipo “this” encontraría un problema: “this” es una
palabra reservada en C#. El siguiente fragmento en C# no compilará:
This × = new this () ;
Un tema similar aparece cuando se accede a miembros,
sobrescribiendo métodos virtuales e identificando espacios de nombres. En C#,
colocando la arroba (@) antes del identificador, se forzará a
ser considerado como un identificador en vez de una palabra reservada por el
compilador. El signo arroba no es considerado parte del identificador.
@this × = new @this ()
;
Por consistencia, esta utilización
también se permite en configuraciones no-públicas como variables locales,
nombres de parámetros y miembros privados.
CONCLUSIONES
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
En los lenguajes informáticos, una palabra reservada es una palabra que tiene un significado gramatical especial para ese lenguaje y no puede ser utilizada como un identificador
en ese lenguaje.
Ocasionalmente
la especificación de un lenguaje de programación puede tener palabras
reservadas que están previstas para un posible uso en futuras versiones.
No hay comentarios:
Publicar un comentario