Вы находитесь на странице: 1из 27

Sesin 7

Punteros

Ms. Ing. CARLOS AURELIO ROMERO SHOLLANDE caromerosh@yahoo.es


UNIVERSIDAD NACIONAL DE TRUJILLO Trujillo - Per

Introduccin
Un puntero es una variable que tiene la direccin de memoria de otra variable que contiene un valor. 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.
Direccin 1001 1002 Valor R

1003
1004 ..

Memoria

Introduccin
Si una variable contiene la direccin de otra variable entonces se dice que: la primera variable apunta a la segunda.
Direccin 2101 2102 2103 2104

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

2105
2106 ..

Introduccin
Referencia directa e indirecta a una variable.
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

cont

23

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;
punt 4000 3500 3500 cont 23

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.

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.
Direccin 3500 3504 3508 3512 3516

y[0]

y[1]

y[2]

y[3]

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.
INDIRECCION SIMPLE INDIRECCION MULTIPLE Puntero Direccin Variable Valor

Puntero
Direccin

Puntero
Direccin

Variable
Valor

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(); }

Вам также может понравиться