You are on page 1of 8

Puntero (informtica)

En ciencias de la computacin, un puntero es un objeto del lenguaje de programacin, cuyo valor


se refiere a (o "apunta a") otro valor almacenado en otra parte de la memoria del
ordenador utilizando su direccin. Un punteroreferencia a una ubicacin en memoria, y a la
obtencin del valor almacenado en esa ubicacin se la conoce comodesreferenciacin del puntero.
A modo de analoga, un nmero de pgina en el ndice de un libro podra considerarse un puntero a
la pgina correspondiente; desreferenciar un puntero sera como ir a la pgina con el nmero de
pgina especificada en el ndice.

eclaracin

Los punteros se declaran con un asterisco, de esta forma:

tipo * variable;

Por ejemplo:

int* puntero;
Se dice que la variable puntero es un puntero a enteros (apunta a
un entero).

Asignacin

El valor que puede adquirir un puntero es, por ejemplo, la direccin


de una variable.
El operador & devuelve la direccin de una variable:

puntero = &variable;

Desreferencia de un puntero

Se puede alterar la variable a la que apunta un puntero.


Para ello se emplea el operador de desreferencia, que es el
asterisco:

*puntero = 45;

En este caso, se est introduciendo un 45 en la posicin de memoria


a la que apunta puntero.

Operaciones con punteros


Un puntero es un tipo de dato similar a un entero, y hay un conjunto
de operaciones definidas para punteros:

La suma o resta de un entero produce una nueva localizacin


de memoria.
Se pueden comparar punteros, utilizando expresiones lgicas,
para ver si estn apuntando o no a la misma direccin de
memoria.
La resta de dos punteros da como resultado el nmero de
variables entre las dos direcciones.
Veamos un ejemplo de utilizacin de punteros:
#include <iostream.h>
main()
{
int vector[3];
int* princPunt = vector;
int* finPunt = &vector[2];
vector[2] = 15;
cout << *(princPunt+2) << '\t' << *finPunt <<'\n';

if (princPunt == finPunt)
cout << " Esto no puede suceder " << '\n';
cout << "Numero de elementos \t" <<finPunt-princPunt << '\n';
}

El resultado de la ejecucin de este programa es:


15
15
Numero de elementos

La declaracin de un tipo de funcin


Comenzemos con un ejemplo. Qul es el tipo de la siguiente funcin?

int una_funcin(char parmetro);


La solucin es

int (*puntero_a_una_funcin)(char)
Para extraer el tipo de la declaracin de funcin hemos hecho lo siguiente:
1.
2.
3.

Hemos eliminado los nombres de los parmetros.


Hemos puesto un asterisco delante el nombre del tipo y hemos puesto todo esto entre
parntesis.
Hemos reemplazado el nombre de la funcin por el nombre puntero_a_una_funcin.

Echemos un vistazo ms detallado.


Los nombres de los parmetros ya no aparecen. El tipo de una funcin es el mismo, si el valor de
retorno y si los parmetros tienen el mismo tipo. Los nombres que tienen no influyen. El nombre de la
funcin desaparece tambin. El nombre de la funcin juega un papel similar como un valor
constante para una variable. El tipo de la variable no depende del nombre de una constante.
El asterisco indica que el tipo es un puntero. Lo ponemos entre parntesis por la preferencia de
operadores del lenguaje. Sin ellas habra un error de sintxis, porque la llamada de funcin
(parntesis tras un identificador) tiene mayor prioridad que el operador asterisco.
Finalmente hemos cambiado el nombre. Decir ms correctamente, hemos introducido un nuevo
nombre. Este nuevo nombre puntero_a_una_funcinrepresenta una variable que puede
guardar la direccin de una funcincon el tipo especificado.

Como el uso de tipos de funciones es poco legible, se suele casi siempre definir un tipo de funcin
mediante un typedef. Esto lo hacemos aqu tambin.

int una_funcin(char parmetro);

2
3

// Definicin de una variable direccin_de_una_funcin

int (*direccin_de_una_funcin)(char) = NULL;

5
6
7

// Definicin de un tipo con typedef.


typedef int (*TIPO_DE_UNA_FUNCIN)(char);

8
9

// Definicin de una variable con el tipo de typedef

10

// Se inicializa la variable con la direccin de


una_funcin.

11

TIPO_DE_UNA_FUNCIN otra_direccin = una_funcin;

Por cierto, algo as no se puede hacer:

// Error

int (*direccin_de_una_funcin)(char) =

int una_funcin(char parmetro);

Esta lnea hara algo como delcarar una_funcin y asignar su direccin al mismo instante. Esto no
est permitido.

Usar un puntero de funcin


Tras saber expresar el tipo de una funcin nos interesa usarlo. Lo podemos usar directamente para
definir una variable.

// Una funcin que ya conocemos.


int una_funcin(char parmetro);

2
3
4
5
6

// Definimos nuestro tipo de funcin y una variable.


typedef int (*TIPO_DE_UNA_FUNCIN)(char);
TIPO_DE_UNA_FUNCIN puntero_a_una_funcin = una_funcin;

7
8

// El valor de una variable se puede asignar a otra.


TIPO_DE_UNA_FUNCIN otro_puntero = puntero_a_una_funcin;

9
10
11
12
13
14
15

// Se pueden comparar punteros de funciones,


// pero no se pueden aplicar las operaciones aritmticas
// de los punteros a constantes y variables.
const bool igual =
puntero_a_una_funcin == otro_puntero; // Bien
puntero_a_una_funcin++; // Error de compilacin

16
17

// Y, desde luego, podemos llamar a una funcin

18

// Se puede usar dos sintaxis diferentes

19

const char parmetro = 'a';

20

const int resultado = puntero_a_una_funcin(parmetro);

21

const int resultado2 = (*puntero_a_una_funcin)


(parmetro);

22
Que se puede llamar a una funcin con dos sintxis diferentes es un tanto peculiar, ya que
suele haber una diferencia importante entre en un puntero y un puntero dereferenciado. Pero
compilan los dos.
La pregunta es: ?cul de las dos formas es la preferible? Pues, es cuestin de gusto. Yo prefiero la
forma (*puntero_a_una_funcin)() ya que deja ms claro que punter_a_una_funcin el el
nombre de una variable y no de una funcin.

Como C y C++ permiten conversiones entre todo tipo de punteros, se puedenconvertir tambin los
punteros de funciones a punteros de variables.

// Obtenemos un puntero de variable a mi funcin.

int una_funcin(char parmetro);

char* puntero_a_datos = (char*)una_funcin;

4
5

// Con este puntero_a_datos no slo puedes leer el cdigo

// ejecutable de la funcin. Tambin puedes modificarlo.

puntero_a_datos[5] = 0xFF;

Es obvio, que estas conversiones son ideales para hackers, pero ser poco probable que se necesitan
durante un uso normal del lenguaje. Por eso puedes esperar que el compilador te avisar con
insistencia. Adems, el cdigo ejecutable de una funcin es de slo lectura. O debera. Conseguir
asignar algo a la memoria del cdigo ejecutable es una manera excelente para introducir un error que
no se encontrar hasta que alguien intente llamar a esta funcin.

Si pasa o retorna una direccin (ya sea un puntero o una referencia), el


programador cliente puede recoger y modificar el valor al que apunta. Si
hace que el puntero o referencia sea constante, impedir que esto suceda,
lo que puede ahorrarle problemas. De hecho, cada vez que se pasa una
direccin como parmetro a una funcin, debera hacerla constante
siempre que sea posible. Si no lo hace, est excluyendo la posibilidad de
usar la funcin con constantes.
La opcin de devolver un puntero o referencia constante depende de lo
que quiera permitir hacer al programador cliente. Aqu se muestra un
ejemplo que demuestra el uso de punteros constantes como argumentos de
funciones y valores de retorno.
//: C08:ConstPointer.cpp
// Constant pointer arg/return

void t(int*) {}

void u(const int* cip) {


//!

*cip = 2; // Illegal -- modifies value

int i = *cip; // OK -- copies value


//!

int* ip2 = cip; // Illegal: non-const

const char* v() {


// Returns address of static character array:
return "result of function v()";
}

const int* const w() {


static int i;
return &i;
}

int main() {
int x = 0;
int* ip = &x;
const int* cip = &x;

t(ip);
//!

// OK

t(cip); // Not OK

u(ip);

// OK

u(cip); // Also OK
//!

char* cp = v(); // Not OK

const char* ccp = v(); // OK


//!

int* ip2 = w(); // Not OK

const int* const ccip = w(); // OK


const int* cip2 = w(); // OK
//!

*w() = 1; // Not OK

} ///:~

Para qu sirve un puntero y cmo se usa

Los punteros tienen muchas utilidades; por ejemplo, nos permiten pasar
argumentos (o parmetros) a una funcin y modificarlos. Tambin permiten el manejo
de cadenas y de arrays. Otro uso importante es que nos permiten acceder directamente
a la pantalla, al teclado y a todos los componentes del ordenador. Si slo sirvieran
para almacenar direcciones de memoria no seran de mucha utilidad. Nos deben dejar
tambin la posibilidad de acceder al contenido de esas posiciones de memoria. Para
ello se usa el operador * (operador de indireccin), que no hay que confundir con el
de la multiplicacin.

You might also like