Upload
mago-julio-cesar
View
4.982
Download
2
Embed Size (px)
Citation preview
Ing. Julio César Canelón RangelActualizado: Abril 2007
Punteros (apuntadores)
Cuando el compilador encuentra declaraciones como: int varInt = 1234; double varDouble = 1.2364; char varChar = ‘a’;
Se crean dichas variables, lo cual significa que: Se reserva la memoria para un valor del tipo especificado. El nombre de la variable se asocia con la dirección de esa
memoria. La memoria se inicializa con valores procedentes a la
declaración (si los hay)
Ing. Julio César Canelón RangelActualizado: Abril 2007
Mapa de Memoria0x00528320
0x00528321
0x00528322
0x00528323
0x00528324
0x00528325
0x00528326
0x00528327
0x00528328
0x00528329
0x0052832a
0x0052832b
0x0052832c
Ing. Julio César Canelón RangelActualizado: Abril 2007
Punteros (apuntadores)
Por tanto, si la dirección de la siguiente posición de memoria disponible es 0x005208320 y los valores de tipo char ocupan 1 byte int ocupan 4 bytes double ocupan 8 bytes
se reservará la memoria de la forma mostrada en el mapa de memoria siguiente.
Ing. Julio César Canelón RangelActualizado: Abril 2007
Mapa de Memoria0x00528320
0x00528321
0x00528322
0x00528323
0x00528324
0x00528325
0x00528326
0x00528327
0x00528328
0x00528329
0x0052832a
0x0052832b
0x0052832c
varInt
varDouble
varChar
int varInt = 1234;double varDouble = 1.2364;char varChar = ‘a’;
int ocupan 4 bytesdouble ocupan 8 byteschar ocupan 1 byte
Ing. Julio César Canelón RangelActualizado: Abril 2007
Punteros
Se puede obtener la dirección de una variable con el operador de obtención de direccion (&).
&variable es la dirección de la variable Por tanto en el ejemplo anterior, tenemos:
&varInt es 0x005208320 &varDouble es 0x00520324 &varChar es 0x00520832c
Ing. Julio César Canelón RangelActualizado: Abril 2007
Punteros
Para aprovechar la utilidad de las dirección de memoria, C++ proporciona variables puntero. Una variable puntero (o simplemente puntero) es una variable cuyo valor es una dirección de memoria que apunta a un valor de un tipo de dato específico.
Ing. Julio César Canelón RangelActualizado: Abril 2007
Declaración de punteros
Formas: Tipo *variablePuntero; Tipo *variablePuntero = direccion;DondeTipo es cualquier tipo de dato y direccion es la dirección de un
objeto del Tipo especificado Propósito:
El operador asterisco * debe preceder a cada identificador de tipo puntero.
En la segunda versión, la dirección de inicialización debe ser la de un objeto del mismo tipo que aquel apunta el puntero. (si tipo es entero entonces la dirección debe corresponder a un objeto entero.
Se puede asignar 0 a cualquier variable puntero, es decir dirección nula (NULL).
Ing. Julio César Canelón RangelActualizado: Abril 2007
Ejemplo include <iostream.h> void main () { int i = 11; int j = 22; double d = 3.3; dobule e = 4.4; int *pi, *pj; double *pd, *pe; pi = &i; pj = &j; pd = &d; pe = &e; cout << "&i = " << pi << endl; cout << "&j = " << pj << endl; cout << "&d = " << pd << endl; cout << "&e = " << pe << endl; }
Ing. Julio César Canelón RangelActualizado: Abril 2007
Punteros
Se podría visualizar el mapa de memoria para el ejercicio anterior de la siguiente manera:
0xbffffd20 11
0xbffffd24 22
0xbffffd30 4.4
0xbffffd28 3.3
0xbffffd20
0xbffffd24
0xbffffd28
0xbffffd30
i
j
d
e
pi
pj
pd
pe
Ing. Julio César Canelón RangelActualizado: Abril 2007
Punteros
Importante recordar que el operador asterisco * debe preceder a cada variable en una declaración de puntero. Double * pDouble;
Una forma para hacer la innecesaria la utilización del asterisco el la siguiente
Typedef double * PunteroDouble; Después usar el PunteroDouble para declarar los
punteros PunteroDouble pi, pj, pk;
Ing. Julio César Canelón RangelActualizado: Abril 2007
Operaciones Básicas Desreferenciación e indirección: Una variable
puntero almacena sólo la dirección de una posición de memoria. Acceder al contenido de dicha posición de memoria a través del puntero requiere el uso de un operador especial *, denominado operador de desreferenciación. *variablePuntero Esta expresión proporciona acceso a la posición de
memoria cuya dirección está almacenada en variablePuntero, si dicha dirección de memoria ya tiene nombre, podemos considerar *variablePuntero como un alias a dicha posición
Ing. Julio César Canelón RangelActualizado: Abril 2007
Ejemploinclude <iostream.h> void main () { int i = 11; int j = 22; double d = 3.3; dobule e = 4.4; int *pi, *pj; double *pd, *pe; pi = &i; pj = &j; pd = &d; pe = &e; cout << “\n”En la dirección “ << pi << “, esta almacenado el valor “ << *pi << “\n”; cout << “\n”En la dirección “ << pj << “, esta almacenado el valor “ << *pj << “\n”; cout << “\n”En la dirección “ << pd << “, esta almacenado el valor “ << *pd << “\n”; cout << “\n”En la dirección “ << pe << “, esta almacenado el valor “ << *pe << “\n”;
Ing. Julio César Canelón RangelActualizado: Abril 2007
Punteros
Con lo anteriormente descrito entonces en base al ejemplo anterior podríamos tener:
int x;
x = *pi + *pj;
cuyo resultado seria x = 33; También podríamos realizar la siguiente
asignación:
*pi = 12;
Ing. Julio César Canelón RangelActualizado: Abril 2007
Punteros
El operador de indirección puede aplicarse más de una vez para producir niveles adicionales de indirección. int **p;
o también es válido
typedef int PunteroInt;PunteroInt *p
Se declara a p como un puntero a una posición de memoria que contiene a su vez un puntero a otra posición de memoria donde se puede almacenar un int
Ing. Julio César Canelón RangelActualizado: Abril 2007
Puntero descolgado
Se debe tener cuidado antes de desreferenciar un puntero y asegurarse que el puntero no es nulo y apunta a una posición concreta de la memoria, ya que la desferenciación de un puntero nulo o indefinido causa normalmente un error fatal en tiempo de ejecución. Este problema se le conoce como puntero descolgado.
Ing. Julio César Canelón RangelActualizado: Abril 2007
Punteros Asignación
A las variables puntero se les puede asignar valores de otras variables puntero siempre que este ligadas al mismo tipo de dato.
Ejemplo, si agregáramos la siguiente línea al programa anterior pi = pj;
El valor de pj se copiaría en pi de forma que tendrían la misma dirección de memoria como valor, es decir ambas apuntarían a la misma posición de memoria.
Ing. Julio César Canelón RangelActualizado: Abril 2007
Punteros Comparación
Los operadores relacionales se pueden usar para comparar dos punteros siempre que estén ligados al mismo tipo. Lo más habitual es usar == y != para determinar si dos sectores de memoria. Ejem: pi != pj; pi != null;
No se pueden comparar dos punteros de tipos de datos diferentes. Ejem:
int *pi; double *pd;
if (pi == pd) //expresión no válida
Ing. Julio César Canelón RangelActualizado: Abril 2007
Reserva de memoria dinámica: Operador new Durante la ejecución de un programa se
puede solicitar memoria al sistema operativo usando la operación new. New Tipo.
Donde Tipo puede ser cualquier tipo. Dicha expresión solicita en tiempo de ejecución un bloque de memoria suficientemente grande para almacenar un valor del Tipo especificado
Ing. Julio César Canelón RangelActualizado: Abril 2007
Reserva de memoria dinámica: Operador new Si se puede satisfacer la petición, new
devuelve una dirección la cual puede almacenarse en variables puntero.
Esta operación se utiliza generalmente al lado de un puntero. Ejem:
int * pInt;
pInt = new int;
new int solicita al S.O. un bloque de memoria suficientemente grande para almacenar un valor entero (es decir
(sizeof(int) bytes de memoria). Si el S.O. puede satisfacer la petición, a pInt
se le asiganará la dirección de esa dirección de memoria
0x13eff860
pInt0x13eff860
Ing. Julio César Canelón RangelActualizado: Abril 2007
Reserva de memoria dinámica: Operador new Como no existe un nombre asociado a la nueva
posición de memoria, recibe el nombre de variable anónima; no se puede acceder directamente a ella de la misma manera que se puede acceder al resto de las variables. Sin embargo, su dirección se guarda en pInt por lo que se puede acceder indirectamente a dicha variable anónima desreferenciando pInt, mediante la expresión *pInt.
A la variable anónima se le puede hacer cosa que se puede hacer con una variable “ordinaria”
Ing. Julio César Canelón RangelActualizado: Abril 2007
Parámetros por Referencia
Considerando la siguiente función C++ que intercambia valores entre dos variables enteras.void intercambiar(int &primero, int &segundo)
{
int temp = primero;
primero = segundo;
segundo = temp;
}
Aquí los parámetros están por referencia porque tiene el &.
Entonces para llamar la función dentro de mi programa sería: intercambiar(x, y);
Ing. Julio César Canelón RangelActualizado: Abril 2007
Parámetros por Referencia
Para hacer el mismo efecto pero usando apuntadores sería:void intercambiar(int *primero, int *segundo){
int temp = *primero;*primero = *segundo;*segundo = *primero;
} La función se llamaría en mi programa:
intercambiar(&x, &y);