Qu es un puntero? Por definicin un puntero es una variable que puede almacenar la direccin en memoria de otra variable. Segn mi definicin, un puntero es una entidad, que puede ser variable o constante, que siempre contiene una direccin de memoria (valida, invlida o nula), en la cual puede estar alojada una entidad de nuestro programa o no. La declaracin de una variable tipo puntero debe ser de la forma:
TipoVariableApuntada *NombreVariablePuntero;
Una variable de tipo puntero debe ser de igual tipo que la variable cuya direccin en memoria contiene, o dicho de otra forma, la variable a la que apunta. Un puntero no tiene asociacin directa con el dato actual, pero si una asociacin indirecta. Por ese motivo se usa el termino indireccin cuando se hace referencia a una asociacin indirecta.
Asignaciones de punteros Cuando el compilador encuentra la declaracin de una variable, le asigna una direccin en memoria en la que se almacenarn los valores que sucesivamente se le asignen a esa variable. El operador & antepuesto al nombre de una variable retorna el valor de la direccin inicial de memoria donde el compilador almacen o almacenar el valor de la variable. Para acceder al valor que se encuentra en la direccin apuntada por un puntero se debe "dereferenciar" el puntero colocando * delante del mismo. Por estos motivos se suele denominar a & el operador de referencia y a * el operador de indireccin. Veamos un ejemplo.
int *puntero; // Declara un puntero a una variable tipo int int variable; /* Declara una variable tipo int. El compilador identifica y asigna direccion (supongamos 0x2710, en Hexadecimal) al identificador <variable> */ variable = 123456; /* Almacena en las direcciones 0x2710, 0x2711, 0x2712 y 0x2713 el valor <123456>, tomando en cuenta que una variable de tipo int ocupa 4 bytes. Verifiquenlo en su compilador con sizeof(int) */ puntero = &variable; // Almacena 0x2710 en <puntero>
El operador * antepuesto a una variable puntero devuelve el valor que sta almacena, partiendo de su direccin inicial, en un nmero de celdas de memoria, que viene definido por el tipo de la variable apuntada. Entonces, siguiendo con el ejemplo anterior:
Recopilado por Rubn Arriagada Daz Ingeniero en Computacin e Informtica Docente IPLA Sede Temuco 2
int otra_variable; // Declara una variable tipo int otra_variable = *puntero; /* Almacena en <otra_variable> el valor <123456>, el valor que contiene <variable> que es apuntada por <puntero> */
Aritmtica de punteros Acabamos de ver asignaciones de punteros. Ahora veamos la aritmtica de punteros. Una variable del tipo char ocupa 1 byte en la memoria y una variable de tipo int ocupa 4 bytes (verifiquen que tamao tienen estos tipos de datos en sus compiladores). Ahora bien, supongamos que creamos una variable de tipo char y sta se aloja en la direccin 0x400, luego creamos un puntero a esa variable.
char c; // se crea en 0x400 char* pc; pc = &c; // pc ahora apunta a 0x400
Utilizando los operadores de adicin y sustraccin podemos movernos a partir de la direccin relativa a la que apunta un puntero.
pc = pc + 1; /* pc ahora apunta a una direccion distinta, ya que se ha desplazado 1 byte en sentido positivo (1 direccion de memoria ms alta), es decir que pc paso de apuntar de 0x400 a 0x401 */
Para volver a la posicin anterior solo debemos escribir: pc-- o pc = pc - 1 o pc -= 1, es indistinto. Lo mismo ocurre con el operador +.
Si utilizamos otro tipo de dato, como por ejemplo int que ocupa 4 bytes, nos moveremos 4 unidades hacia delante (+) o hacia detrs (-) dependiendo del operador que utilicemos.
Comparacin de punteros Para la comparacin de punteros se utilizan los operadores bsicos de comparacin que usbamos con variables bases, tales como int. Por lo que para saber por ejemplo si un puntero apunta a la misma direccin a la que apunta otro, utilizaramos: p1 == p2, para saber si son distintos utilizaramos el operador !=, para saber si p1 apunta a una direccin de memoria mas baja que p2 colocaramos p1 < p2, y as con los dems operadores de comparacin.
Recopilado por Rubn Arriagada Daz Ingeniero en Computacin e Informtica Docente IPLA Sede Temuco 3
Punteros, referencias y punteros a arrays. Utilizacin en las funciones. Estos tres conceptos estn sumamente ligados entre si, y por ende con direccin de memoria. Ya vimos que un puntero es una variable que contiene la direccin en memoria de otra variable, ahora veremos que uso se le puede dar en las funciones.
Los punteros se utilizan en funciones por varios motivos: Manipular completamente las variables que se pasan como argumento a la funcin, permitiendo que los cambios en dichas variables se vean reflejados fuera de ella.
* Recuperar de una funcin ms de un valor. * Optimizar el procesamiento. * Retornar referencias
Este ejemplo cumple con los tres primeros motivos mencionados (Referencias se ve en breve).
void intercambiar(int *a, int *b) { int aux; aux = *a; *a = *b; *b = aux; }
La funcin intercambia dos valores. Para ello solicita dos punteros a enteros, utilizando para acceder a estos valores, el operador de indireccin (*). La llamada a la misma se realiza utilizando el operador de referencia (&).
int a = 1, b = 3; intercambiar(&a, &b); //como resultado la funcion intercambia los valores, a = 3 y b = 1
Si lo que queremos es retornar un puntero deberemos definir la funcin de otra forma, as que dmosle adems una nueva funcionalidad, retornando el puntero al mayor de los dos nmeros de sta manera.
int* intercambiar(int *a, int *b) { int aux; aux = *a; *a = *b; *b = aux; return (*a > *b)? a: b;
Recopilado por Rubn Arriagada Daz Ingeniero en Computacin e Informtica Docente IPLA Sede Temuco 4
}
int a = 1, b = 3, *c; c = intercambiar(&a,&b); ShowMessage("El mayor es: " + IntToStr(*c)); // que esta en a y en c
Referencias Las referencias son seudnimos o alias que se aplican a otra entidad del mismo tipo. Para declarar una referencia se coloca & despus del tipo de variable y antes del identificador de la misma. Las variables de referencias necesitan inicializacin y ste valor (variable o literal) no podr ser modificado.
int a; // supongamos direccion 0x2740 a = 5; // se asigna el valor 5 a la variable int& b = a; // creamos la referencia b a la variable a
Tanto a como b estn en la misma direccin de memoria, de tal manera que al modificar una de ellas, se modifica la otra. Siguiendo el ejemplo la direccin de b es 0x2740 (la misma que a).
b = 7; // tanto a como b ahora almacenan 7 a = 0; // tanto a como b ahora almacenan 0
Por lo tanto, las referencias, se pueden pensar como punteros a una direccin de memoria fija. Siguiendo con el ejemplo anterior, pero con referencias:
void intercambiar(int &a, int &b) { int aux; aux = a; a = b; b = aux; }
int a = 1, b = 3; intercambiar(a, b); //como resultado la funcin intercambia los valores, a = 3 y b = 1
Tanto el cdigo con punteros como ste ultimo con referencias arrojan el mismo resultado, con la ventaja que el ltimo permite no utilizar el operador de indireccin, adems en C++ las referencias son muy utilizadas para pasar argumentos a funciones (y como valores de retorno), no slo para poderlos
Recopilado por Rubn Arriagada Daz Ingeniero en Computacin e Informtica Docente IPLA Sede Temuco 5
modificar dentro de la funcin, sino tambin por motivos de eficiencia, pues es mucho ms rpido pasar un puntero o una referencia de una variable que una copia del valor de esa variable. Si adems la variable es una estructura, las ventajas de eficiencia son todava mucho ms notables. No se debe confundir el uso de (&) en la declaracin de una referencia con el operador direccin (&), de la misma forma que no se debe confundir el carcter (*) en la declaracin de un puntero, con el operador indireccin (*).
El que una funcin tenga como valor de retorno una variable tipo referencia permite utilizarla de una manera un poco singular. Considrese el siguiente ejemplo:
int& intercambiar(int &a, int &b) { int aux; aux = a; a = b; b = aux; return (a > b)? a: b; }
Esto permite utilizarla, por ejemplo, del siguiente modo:
int a = 1, b = 3; intercambiar(a,b) = 0;
sta es una forma un poco extraa de utilizar una funcin: la llamada est a la izquierda del operador de asignacin, en vez de aparecer a la derecha en una expresin aritmtica o de otro tipo. El resultado de esta llamada tambin es un poco extrao: el valor de retorno es una referencia, esto es un alias del argumento de valor mximo. Cuando la llamada a la funcin se sustituye por su valor de retorno, el resultado de la sentencia anterior es que la variable pasada como argumento que tiene mayor valor se hace igual a cero. Este mismo efecto puede conseguirse mediante punteros, pero con referencias resulta mucho ms sencillo.
Los Arrays son punteros Los arrays no pueden ser declarados como variables referencia, porque ya tienen una forma propia y natural de ser pasados como argumentos a una funcin. Pero primero definamos como asignar un array de una dimensin a un puntero.
Recopilado por Rubn Arriagada Daz Ingeniero en Computacin e Informtica Docente IPLA Sede Temuco 6
int array[5]; int *p; p = array; // p = &array[0]; la direccion del primer elemento [0]
Para un array de 2 dimensiones
int array[5][4]; int *p; p = &array[0][0]; // la direccion del primer elemento [0][0]
Para un array de 3 o mas dimensiones (tres en este ejemplo).
int array[5][4][3]; int *p; p = &array[0][0][0]; // la direccion del primer elemento [0][0][0]
Por lo que un array se puede pensar como un puntero a la direccin inicial de memoria donde comienza. Creamos un procedimiento que inicialice el array de una dimensin, para esto podemos definirlo de varias maneras, la primera pide un array de enteros de 5 elementos, la segunda un array de enteros con cantidad de elementos desconocidos, la tercera un puntero a un entero y la ltima un array de 4567 elementos, en realidad todas estn pidiendo un puntero a la direccin del primer elemento del array.