Beruflich Dokumente
Kultur Dokumente
Departamento de Ingeniera
Estructura de Datos
Direcciones y
punteros.......................................................4
PUNTERO A PUNTERO.................................................................6
PUNTEROS A VOID......................................................................8
STRING Y
PUNTEROS...................................................................9
PUNTEROS A FUNCIONES..........................................................13
CONCLUSIN.............................................................................1
6
2
PUNTEROS
El concepto de puntero est unido a la forma en que los tipos de
datos son almacenados en la memoria de un ordenador, ya que denotan
la direccin (address) o localizacin de una variable determinada. El
nombre de la variable determina el tipo (char, int, float o double) y su
direccin determina dnde est almacenada. Conocer la direccin de
una variable es importante porque:
Permite que las funciones cambien el valor de sus argumentos,
como veremos en el captulo siguiente.
Permite pasar vectores de forma eficiente entre funciones: en
lugar de copiar cada elemento del vector, se copia la direccin del
primer elemento.
Permite reservar memoria en tiempo de ejecucin en lugar de en
tiempo de compilacin, lo que significa que el tamao de un vector
puede ser determinado por el usuario en lugar de por el
programador.
Terminologa bsica.
3
hexadecimal, pudiendo contener un carcter, un entero o un real
(aunque en realidad todos son almacenados como nmeros binarios).
Para obtener la direccin de una variable se utiliza el operador
direccin &:
#include <iostream.h>
main()
{
double d = 2.7183;
cout << "numero = " << d << "\tdireccin = " << &d << '\n';
}
Direcciones y punteros
4
int *puntero1;
int *puntero2, *puntero3;
char variable, *punteroCaracter;
float *punteroReal, real;
# include <iostream.h>
main ()
{
int *ptInt;
int var1 = 7, var2 = 27;
ptInt = &var1;
var2 = *ptInt;
cout << " var1 = " << var1 << " var2 = " <<var2 << "*ptInt = " <<*ptInt << '\n';
*ptInt = 5;
cout << " var1 = " << var1 << " var2 = " <<var2 << "*ptInt = " <<*ptInt << '\n';
ptInt = &*ptInt;
var1 = *&var1;
}
5
izquierda a derecha, por tanto el ms cercano a la variable es
siempre el primero que se aplica.
PUNTERO A PUNTERO
Un puntero almacena la direccin de un objeto, puesto que ese
objeto puede ser otro puntero, es posible declarar un puntero que
apunta a puntero. La notacin de puntero a puntero requiere de un
doble asterisco, '**', la sola notacin suele generar un efecto de
confusin considerable, y es la razn de sugerir en lo posible reemplazar
punteros a punteros por alguna otra alternativa (una clase con miembro
puntero).
int a = 4;
int* pt1 = &a;
int**pt2 = &pt1;
int a = 4; 0xfff6 4
6
cout<<pt2; //Imprime la direccion del propio puntero 'pt2', aqui: "0xfff2"
cout<<*pt2; //Imprime la direccion almacenada en 'pt2', "0xfff4"
cout<<**pt2; //Imprime el valor almacenado en '*pt1 = a', "4".
7
PUNTERO A VOID
El puntero a void es tambin un elemento del ANSI-C. A un
puntero a void puede asignarse el valor de cualquier puntero de otro
tipo. Por ejemplo, en el siguiente programa, al puntero general se le
asigna primero la direccin de un entero, y despus la de un nmero
real:
#include <iostream.h>
main ()
{
int *ptInt;
float *ptFloat;
int var1 = 7, var2 = 27;
float x = 1.2345, y = 32.14;
void *general;
ptInt = &var1;
*ptInt += var2;
cout << " var1 tiene ahora el valor \t" << *ptInt << '\n';
general = ptInt;
ptFloat = &x;
y += 5 * (*ptFloat);
cout << " y tiene ahora el valor \t" << y << '\n';
general = ptFloat;
}
8
malloc(), que devuelve un puntero a void. Este puntero puede ser
asignado a un puntero de cualquier tipo, transfiriendo el puntero
devuelto al tipo correcto.
Un puntero a void se almacena en memoria de forma que puede
ser utilizado con cualquiera de los tipos simples predefinidos en C++,
pero tambin pueden ser utilizados con los tipos compuestos que el
usuario define, puesto que los tipos compuestos estn formados por
tipos simples.
STRING Y PUNTEROS
Se pueden leer datos de un string, y se puede enviar la salida a un
string en memoria. Para ello se debe incluir el fichero strstream.h y
declarar strings de entrada y salida. Un ejemplo de string de salida es el
siguiente:
#include <strstream.h>
main(){
char c[10];
ostrstream stringDeSalida(c,10);
pi= 3.14
#include <strstream.h>
#include <string.h>
main(){
char *s = "5.16 90 hola";
istrstream stringDeEntrada(s,strlen(s));
9
float f;
int i;
char t[10];
5.16 90 hola
# include <iostream.h>
main()
{
int index, *point1, *point2;
point1 = &index;
*point1 = 77;
point2 = new int;
*point2 = 173;
cout <<"Los valores son " << index <<" " << *point1 << " "<< *point2 <<'\n';
point1 = new int;
point2 = point1;
*point1 = 999;
cout <<"Los valores son " << index <<" " << *point1 << " "<< *point2 <<'\n';
delete point1;
float *float_point1, *float_point2 = new float;
float_point1 = new float;
*float_point2 = 3.14159;
*float_point1 = 2.4 * (*float_point2);
delete float_point2;
delete float_point1;
10
char *c_point;
c_point = new char;
delete c_point;
c_point = new char [sizeof(int) + 133];
delete c_point;
}
Resultado de la ejecucin:
11
una llamada subsiguiente, y ser pronto reutilizada en cualquier
programa.
Ya que el operador delete est definido para no hacer nada si se
le pasa un valor NULL, se puede liberar la memoria ocupada por
un dato al que apunta un puntero NULL, ya que realmente no se
est haciendo nada. El operador delete slo puede utilizarse para
liberar memoria asignada con el operador new. Si se usa delete
con cualquier otro tipo de dato, la operacin no est definida, y
por tanto nada sucede.
En el programa tambin declaramos algunas variables reales, y se
realizan operaciones similares a las anteriores. De nuevo esto
ilustra que en C++ las variables no tienen que ser declaradas al
comienzo de cada bloque. Una declaracin es una sentencia
ejecutable y puede entonces aparecer en cualquier lugar en la lista
de sentencias ejecutables.
Finalmente, ya que el operador new requiere un tipo para
determinar el tamao de un bloque dinmicamente asignado, se
muestra cmo asignar un bloque de tamao arbitrario. Esto es
posible utilizando la construccin de las ltimas lneas del
programa, donde un bloque de 37 caracteres de tamao (37
bytes) es reservado. Un bloque de 133 bytes mayor que el tamao
de un entero se asigna posteriormente. Por tanto, el operador
new se puede utilizar con la misma flexibilidad de la funcin
malloc() de C.
Cuando los datos asignados dinmicamente son borrados con
delete, todava quedan en memoria. Si repetimos la instruccin
cout inmediatamente despus de utilizar delete, veremos que
todava se conservan los valores. Si la repetimos de nuevo antes
de dejar el programa, cuando el espacio que ocupaban debe haber
sido sobrescrito, veremos que ya no es as. Incluso aunque el
compilador nos d los nmeros correctos, no es una buena
prctica pensar que esos datos estn ah todava, porque en un
programa dinmico largo la memoria se usar continuadamente.
Las funciones estndar utilizadas en C para manejo dinmico de
memoria, malloc(), calloc() y free(), tambin se pueden utilizar
en C++ de la misma forma que en C. Los operadores new y
delete no deben mezclarse con estas funciones, ya que los
resultados pueden ser impredecibles. Si se est partiendo de
cdigo C, lo mejor es continuar utilizando las funciones en las
nuevas lneas de programa. Si no es as, se deben utilizar los
nuevos operadores, ya que se han construido como parte del
lenguaje en s, ms que aadirse, y por tanto son ms eficientes.
Cuando se utiliza new para asignar memoria para un vector, el
tamao del vector se sita entre corchetes, siguiendo al tipo:
12
int *intvector;
intvector = new int [20];
y se libera:
delete [] intvector;
PUNTEROS A FUNCIONES
Los punteros a funciones ya existan en C, aunque no se utilizan
regularmente. Veamos un ejemplo:
#include <iostream.h>
13
Esta es la funcion printMensaje
Esta es la funcion printMensaje
Este es el dato: 3.14159
Este es el dato: 3.14159
error: In this statement, the referenced type of the pointer value "print_int" is
"function (int) returning void", which is not compatible with "function (float) returning
void". Compilation terminated with errors.
14
ARREGLOS DE TAMAO VARIABLE
Mediante el uso de los operadores new y delete se puede
determinar el tamao de un array en tiempo de ejecucin. La lnea:
#include <iostream.h>
main(){
int n;
cin >> n;
float* const p = new float[n];
15
CONCLUSIN
En estas lneas nos hemos dedicado a aprender y
comprender un poco mas lo que son los punteros, sus distintas
clases y usos, y se ha visto como con su implementacin se
pueden realizar distintos tipos de algoritmos, facilitando el uso
de memoria y haciendo mas dinmicos los programas realizados
con su uso.
Nos hemos dado cuenta que sin ellos seria casi imposible
en C y C++ realizar ciertas aplicaciones que requieren un manejo
excesivo de memoria, dando la oportunidad de estructurar los
algoritmos realizados con el fin de que el programador no tenga
que asignar completamente la memoria al realizar el programa y
que sea el usuario final quien a medida que va utilizando la
aplicacin valla pidindole a su computador la memoria que se
va a utilizar sin que este se de cuenta.
16