You are on page 1of 27

Sesin 7

UNIVERSIDAD NACIONAL DE TRUJILLO


Trujillo - Per
Ms. Ing. CARLOS AURELIO ROMERO SHOLLANDE
caromerosh@yahoo.es
Introduccin
Un puntero es una variable que tiene la direccin de
memoria de otra variable que contiene un valor.
1001
1002
1003
1004
..
La direccin es la posicin que
ocupa en la memoria una
variable, un arreglo, una cadena,
una estructura, otro puntero, etc.
Normalmente las variables
contienen valores especficos.
En cambio, los punteros
contienen direcciones de
variables que contienen valores
especficos.
R
Direccin Valor
Memoria
Introduccin
Si una variable contiene la direccin de otra variable
entonces se dice que: la primera variable apunta a la
segunda.
2101
2102
2103
2104
2105
2106
..
Direccin
En este sentido, los nombres de
variables hacen referencia
directa a un valor y los
punteros hacen referencia
indirecta a un valor.
La referencia a un valor a travs
de un puntero se llama
indireccin.
2105
Introduccin
Referencia directa e indirecta a una variable.
cont
23
cont
23
cont hace referencia
directa a una variable
cuyo valor es 23
cont hace referencia
indirecta a una variable
cuyo valor es 23
punt
Introduccin
Existen tres razones para usar punteros en la creacin de
programas:
Los punteros proporcionan los medios mediante los
cuales las funciones modifican sus argumentos de
llamada.
Se pueden utilizar para soportar las rutinas de
asignacin dinmica del C++.
Se puede sustituir por arreglos en muchas situaciones
para incrementar la eficacia.
Variable Puntero
Sintaxis : tipo *nombre_variable;
Propsito : Declarar si una variable contiene una
direccin de memoria. Donde tipo puede ser
cualquier tipo base del C++, y ste define a
que tipo de variable puede apuntar el puntero.
Ejemplo : int *punt, k;
Esta sentencia declara que punt apunta a un valor u objeto
de tipo entero. Cada variable que se declara como puntero
debe ir precedida por un *.
Los punteros se deben inicializar a 0, a NULL o a una
direccin, al declararlos o mediante una asignacin, para
evitar que apunten a reas desconocidas de memoria.
Operadores Puntero
Existen dos operadores especiales de punteros:
& : Operador de direccin, devuelve la direccin de
memoria de su operando (variable a la que precede).
punt = &cont;
Coloca la direccin de memoria 3500 de la variable cont
en punt y la variable puntero punt esta ubicada en la
direccin 4000. Esta direccin es una posicin interna
del ordenador y no tiene que ver con el valor de cont.
Se lee que punt recibe la direccin del valor cont.
4000 3500
punt
23
cont
3500
Operadores Puntero
* : Operador de indireccin, es el complemento de &,
devuelve el valor de la variable situada en la
direccin que sigue (sinnimo de la variable hacia el
que apunta su operando).
valt = *punt;
Si punt contiene la direccin de memoria de la variable
cont, entonces coloca el valor de cont en valt.
Ejemplo, si cont al inicio tena el valor 23, entonces,
despus de esta asignacin, valt tendr el valor 23 ya que
es el valor guardado en la posicin 3500, que es la
direccin de memoria que asign a punt.
Recordar al * como en la direccin.
Se lee como que valt recibe el valor de direccin punt.
Operadores Puntero
El proceso que consiste en reportar el valor de una
variable precedida por un * se conoce como
desreferenciacin de un puntero.
Ejemplo: cout<<*punt;
Esta sentencia reporta el valor de la variable cont, es
decir 23.
Tambin puede utilizarse un puntero desreferenciado del
lado izquierdo de una sentencia de asignacin.
Ejemplo: *punt = 25;
Esta sentencia asigna el valor 25 a la variable cont.
Operadores Puntero
El puntero desreferenciado tambin puede usarse para
recibir un valor de entrada.
Ejemplo: cin>>*punt;
Como el signo de multiplicacin y el de en la direccin
es el mismo, al escribir un programa, tener en cuenta que
estos operadores no tienen relacin.
& y * tienen una precedencia ms alta que el resto de
operadores aritmticos.
El tipo base del puntero determina el tipo de datos que el
compilador asumir que apunta el puntero.
Como punt es un puntero entero, C++ copia dos bytes en
valt desde la direccin a la que apunta punt.
Expresiones con Punteros
a) Se puede usar un puntero en la parte derecha de una
sentencia de asignacin para asignar el valor del
puntero a otro puntero. Ejemplo:
int t, *x, *y;
t = 450; x = &t; y = x;
cout<<La direccin es : << y;
Este fragmento de programa visualiza la direccin de
t en hexadecimal, y no el valor de t.
Expresiones con Punteros
b) En aritmtica convencional el resultado de 3000+2 es
3002. Pero en aritmtica de punteros esto no es as,
pues si a un puntero se le suma (+) o resta (-) un
entero; dicho puntero no aumenta o disminuye en la
misma cantidad que el entero, sino en el entero por el
nmero de bytes de la variable hacia la que apunta.
Nmero de bytes depende de tipo de dato de variable.
Ejemplo: x += 7;
Si la variable x es de tipo entero; entonces, despus de
esta operacin, x apuntar a la direccin 3014 (3000 +
7 * 2), ya que los enteros poseen dos bytes.
Si el ejemplo hubiera sido: x = 4;
Entonces x apunta a la direccin 2992 (3000 4 * 2).
Expresiones con Punteros
c) Se pueden incrementar (++) o disminuir (- -)
punteros. Por ejemplo: sea y un puntero a un nmero
flotante con la direccin actual 3500.
Despus de la expresin: y++;
la direccin de y ser 3504 y no 3501.
Cada vez que se incrementa y, la computadora
apuntar al siguiente flotante, que usa cuatro bytes.
y[0] y[1] y[2] y[3]
Direccin
3500 3504 3508 3512 3516
Expresiones con Punteros
d) Es posible asignar un apuntador a otro, si ambos son del
mismo tipo. De otro modo, es necesario emplear un
operador de conversin mediante cast para convertir el
valor del apuntador del lado derecho de la asignacin al
tipo de apuntador a la izquierda de la asignacin.
e) Es posible comparar dos punteros en una relacin:
if(g>h) cout<<g apunta a direccin ms alta que h;
Se usan las comparaciones de punteros, generalmente,
cuando dos o ms punteros apuntan a un objeto comn.
f) No se pueden realizar otras operaciones sobre punteros;
es decir, no se puede multiplicar o dividir punteros, no
se puede sumar o restar dos punteros y no se puede
sumar o restar los tipos float o double a punteros.
Punteros y Arreglos
Como la velocidad es una consideracin frecuente en
programacin, el uso de punteros es ms comn que el
mtodo de indexacin de arreglos, debido a que C++ tarda
ms en indexar un arreglo que lo que hace el operador *.
El mtodo de los punteros requiere de las siguientes
consideraciones:
a) Un nombre de arreglo sin ndice, es la direccin del
comienzo del arreglo. Es decir, el nombre de un
arreglo es un puntero al arreglo. Ejemplo:
char w[50], *x;
x = w;
Aqu se pone en x la direccin de 1er. elemento de w.
Punteros y Arreglos
b) Debido a que los ndices de arreglos comienzan en cero;
para acceder a un determinado elemento de un arreglo;
por ejemplo el cuarto elemento de w, se puede escribir:
w[3] *(w+3)
c) En el caso del arreglo bidimensional g, cuyos
contadores i y j se inicializan a partir de cero, el acceso
puede especificarse como:
g[i][j] *(*(g + i) + j)
d) Se puede indexar un puntero como si fuera un arreglo:
int g[7] = {1, 2, 3, 4, 5, 6, 7}; int j, *x;
x = g; for(j=0; j<7; j++) cout<<x[j];
Aqu se visualiza en la pantalla los nmeros del 1 al 7.
Punteros y Arreglos
e) El C++ trata a las cadenas como punteros al primer
carcter de cadena y no como cadena propiamente dicha
strlen(char *q) {
int j = 0;
while(*q) { j++; q++; }
return j; }
Recordar que toda cadena termina en un nulo (o falso).
while(*q)
Es verdad hasta que se alcance el final de la cadena.
f) Si se quiere acceder al arreglo aleatoriamente, es mejor
la indexacin, ya que es tan rpido como la evaluacin
por punteros y por que es ms fcil programar.
Punteros y Arreglos
g) Se puede asignar la direccin de un elemento especfico
de un arreglo aplicando el & a un arreglo indexado:
q = &y[7];
Esta sentencia coloca la direccin del octavo elemento
de y en q. Esto es til en la localizacin de subcadenas.
char w[60],*y; int t;
cout<<Introducir una cadena: ; gets(w);
for(t=0; w[t] && w[t]==;t++);
y = &w[t]; cout<<y;
Esto imprime el resto de una cadena, que se introdujo
por teclado, desde el punto en que la computadora
encuentre el primer espacio o el final de la cadena.
Punteros y Arreglos
h) Recordar que el acceso a una cadena individual se
especifica solamente con el ndice izquierdo.
gets(y[i]);
Esta sentencia es funcionalmente equivalente a:
gets(&y[i][j]);
i) Se pueden hacer arreglos de punteros. Ejemplo:
int *b[10];
Declara un arreglo de punteros int de tamao 10.
j) Para asignar una direccin de variable entera llamada z
al quinto elemento del arreglo de punteros, se escribir:
b[4] = &z;
y para encontrar el valor de z se escribir: *b[4]
Punteros a Punteros
Sintaxis : tipo **nombre_variable
Propsito : Declarar un puntero a un puntero, es decir
efectuar un direccionamiento indirecto
mltiple o una cadena de punteros.
Ejemplo : float **pony;
Esta declaracin le dice al compilador que pony es un
puntero a un puntero tipo float, y que no es un puntero a
un nmero en punto flotante.
Valor
Variable
Valor
Variable
INDIRECCION
SIMPLE
INDIRECCION
MULTIPLE
Direccin
Puntero
Direccin
Puntero
Direccin
Puntero
Punteros a Punteros
Como se ve en la figura anterior, en el caso de un
puntero normal, el valor del puntero es la direccin de la
variable que contiene al valor deseado.
En el caso de un puntero a puntero, el primer puntero
contiene la direccin del segundo puntero, que apunta a
la variable que contiene el valor deseado.
Se puede llevar direccionamiento indirecto mltiple a
cualquier extensin, pero en exceso es difcil de seguir y
propensa a errores conceptuales (no confundir
direccionamiento indirecto mltiple con listas enlazadas,
que se usan en aplicaciones como las bases de datos).
Errores con Punteros
Los siguientes son algunos de errores al usar punteros:
- Despus de declarar un puntero, pero antes de asignarle
un valor, contendr un valor desconocido.
Si se trata de usar el puntero antes de asignarle un valor,
es probable que cause un error extremadamente grave,
no slo para el puntero, sino para el sistema.
Se puede asignar a un puntero que apunta a ninguna
parte el valor nulo, para significar que el puntero apunta
a nada o est sin usar. Ejemplo:
for(k=0; x[k]; ++k) if(!strcmp(x[k], q)) break;
El bucle funcionar hasta que la rutina encuentre la
cadena que busca o el puntero nulo, suponiendo que el
ltimo elemento del arreglo x est marcado con un nulo.
Errores con Punteros
- El artificio anterior puede no ser tan seguro.
Si se usa un puntero nulo en el lado izquierdo de una
sentencia de asignacin, se correra todava el riesgo de
estropear el programa o el sistema operativo.
Por lo que se recomienda inicializar las cadenas:
char *g= Buenos Das;
Como se puede ver, el puntero g no es un arreglo.
El C++ crea lo que se llama tabla de cadenas, que se
usan internamente para guardar las constantes de cadena.
Por tanto, esta sentencia de declaracin pone la direccin
de la cadena Buenos Das, almacenada en la tabla de
cadenas, en el puntero g.
En el programa, g se puede usar como otra cadena.
Errores con Punteros
- Otro error es provocado por el mal entendimiento de la
forma de usar un puntero. Ejemplo:
int x, *y;
x = 25; y = x;
cout<<*y;
La llamada cout no imprimir el valor de x, que es 25,
sino algn valor desconocido.
La razn es que la asignacin y = x; es errnea.
La sentencia asigna el valor 25 al puntero y, que se
supone contiene una direccin y no un valor.
La sentencia correcta sera:
y = &z;
Uso de TypeDef
Sintaxis : typedef nom_tipo_actual nuevo_nom_tipo;
Propsito : Crear nuevos nombres de datos o sinnimos
para tipos de datos anteriormente definidos,
esto realmente no crea una nueva clase de
datos sino que lo redefine, a fin de crear
nombres de tipos ms breves.
Ejemplo : typedef float Real;
La sentencia del ejemplo anterior define el nuevo nombre
de tipo Real como un sinnimo para el tipo float. Despus
se puede crear una variable de tipo punto flotante:
Real Numero;
Ejemplo
Dado un arreglo bidimensional, multiplicar cada uno de
sus elementos por una constante igual a 12 y reportar
dichos resultados.
Codificacin:
#include <iostream.h> // MULTIPLICAR MATRIZ * 12
#include <conio.h>
#define M 3 // Nmero de filas de la tabla
#define N 4 // Nmero de columnas de la tabla
main() {
int tabla[M][N] = { {11, 13, 17, 19},
{29, 31, 37, 39},
{41, 43, 47, 49} };
Ejemplo
const int k=12;
int i, j; // Contadores de filas y columnas de la tabla
clrscr();
for(i=0; i<M; i++)
for(j=0; j<N; j++) *(*(tabla + i) + j) *= k;
cout<<"Tabla multiplicada por 12\n\n";
for(i=0; i<M; i++) {
for(j=0; j<N; j++) cout<<*(*(tabla + i) + j)<<" ";
cout<<"\n";
}
getch();
}