Vous êtes sur la page 1sur 21

Historia

Se le atribuye a Harold Lawson la invenci�n del puntero en 1964.2? En 2000, Lawson


fue presentado el Premio Pionero de Inform�tica por la IEEE "[por la invenci�n de
la variable puntero y la introducci�n de este concepto en PL /I, proporcionando
as�, por primera vez, la capacidad de tratar con flexibilidad las listas enlazadas
en un lenguaje de alto nivel de prop�sito general".3? Seg�n el Diccionario ingl�s
de Oxford, la palabra puntero apareci� impresa por primera vez como un puntero de
pila en un memorando t�cnico de la System Development Corporation (Corporaci�n de
Desarrollo de Sistemas).
Descripci�n formal

En ciencias de la computaci�n, un puntero es un tipo de referencia.

Un dato primitivo (o simplemente primitivo) es cualquier dato que puede ser le�do o
escrito en la memoria del ordenador usando un acceso de memoria (por ejemplo, tanto
un byte como una palabra son primitivas).

Un agregado de datos (o simplemente agregado) es un grupo de primitivos que son


l�gicamente contiguos en la memoria y que son vistos colectivamente como un dato
(por ejemplo, un agregado podr�a ser 3 bytes l�gicamente contiguos, los valores de
los cuales representan las 3 coordenadas de un punto en el espacio). Cuando un
agregado est� compuesto enteramente del mismo tipo de primitiva, dicho agregado
puede denominar matriz; en cierto sentido, una palabra multi-byte primitiva es una
matriz de bytes, y algunos programas de usan palabras de esta manera.

Un puntero de memoria (o simplemente puntero) es un valor primitivo del cual est�


destinado a ser utilizado como una direcci�n de memoria; se dice que un puntero
apunta a una direcci�n de memoria. Tambi�n se dice que un puntero apunta a un dato
[en memoria] cuando el valor del puntero es la direcci�n de memoria de referencia.

M�s en general, un puntero es un tipo de referencia, y se dice que un puntero


referencia a un dato almacenado en alg�n lugar de la memoria; para obtener ese dato
se desreferencia el puntero. La caracter�stica que separa punteros de otros tipos
de referencia es que el valor de un puntero est� destinado a ser interpretado como
una direcci�n de memoria, que es un concepto bastante de bajo nivel.

Las referencias sirven como un nivel de indirecci�n: El valor de un puntero


determina que la direcci�n de memoria (es decir, cual dato) est� siendo utilizado
en un c�lculo. Debido a que la indirecci�n es un aspecto fundamental de los
algoritmos, generalmente los punteros son expresados como un tipo de datos
fundamental en lenguajes de programaci�n; en forma de lenguajes de programaci�n
est�ticos (o fuertemente) tipados, el tipo de un puntero determina el tipo de dato
al que apunta el puntero.
Usos en estructuras de datos

Cuando se configuren estructuras de datos como listas, colas y �rboles, es


necesario contar con indicadores para ayudar a controlar c�mo se implementa y
controla la estructura. Ejemplos t�picos de punteros son los de inicio, los
punteros finales y los punteros de pila. Estos indicadores pueden ser o bien
absolutos (direcci�n f�sica real o una direcci�n virtual en la memoria virtual) o
relativos (un desplazamiento desde una direcci�n inicial absoluta ("base") que
suele utilizar menos bits que una direcci�n completa, pero por lo general requieren
una operaci�n aritm�tica adicional para resolverse).

Las direcciones relativas son una forma de segmentaci�n de memoria manual, y


comparten muchas de sus ventajas y desventajas. Una compensaci�n de dos bytes, que
contiene un entero sin signo de 16 bits, se puede utilizar para proporcionar
direccionamiento relativo de hasta 64 kilobytes de una estructura de datos. Esto se
puede extender f�cilmente a 128K, 256K o 512K si la direcci�n apuntada se ve
obligada a alinearse - a mitad de palabras, palabra o doble palabra (pero, lo que
requiere una operaci�n de "desviaci�n a la izquierda" a nivel de bits para 1, 2 o 3
bits-con el fin de ajustar el desplazamiento por un factor de 2, 4 u 8, antes de su
adici�n a la direcci�n de base). Sin embargo, por lo general esos planos tienen un
mont�n de problemas, y por conveniencia para el programador son preferibles las
direcciones absolutas del programador (y subyacente a esa, un espacio de direcci�n
plano).

A un byte offset, tal como el valor ASCII hexadecimal de un car�cter (por ejemplo,
X'29') se puede utilizar para apuntar a un valor alternativo entero (o �ndice) en
una matriz (por ejemplo, X'01'). De esta manera, los caracteres pueden ser
traducidos de manera muy eficiente partiendo de datos brutos, a un �ndice
secuencial utilizable y luego a una direcci�n absoluta sin utilizar una tabla de
b�squeda.
Uso en tablas de control

Por lo general, las tablas de control, que se utilizan para controlar el flujo del
programa hacen un amplio uso de punteros. Los punteros, normalmente integrados en
una entrada de la tabla, pueden, por ejemplo, ser usados para sostener los puntos
de entrada a subrutinas a ser ejecutados, basado en ciertas condiciones definidas
en la misma entrada de la tabla. Sin embargo, los indicadores pueden ser simples
�ndices de otros cuadros distintos, pero relacionados, que comprenden un conjunto
de las direcciones reales o direcciones propias (dependiendo de las construcciones
disponibles del lenguaje de programaci�n). Tambi�n pueden utilizarse para se�alar
(retrocediendo) a entradas de la tabla anterior (como en el procesamiento de bucle)
o avanzar para pasar algunas entradas de la tabla (como en un switch o salida
"prematura" de un bucle). A este �ltimo efecto, el "puntero" simplemente puede ser
el n�mero de entrada de la tabla en s� y puede pasar a ser una direcci�n actual
usando aritm�tica simple.
Or�genes en la arquitectura de ordenador

Los punteros son una abstracci�n muy delgada en la parte superior de las
capacidades de direccionamiento ofrecidas por la mayor�a de las arquitecturas
modernas. En el esquema m�s simple, una direcci�n, o un �ndice num�rico, se asigna
a cada unidad de memoria en el sistema, donde la unidad es t�picamente un byte o
una palabra - dependiendo de si la arquitectura es direccionable por byte o
direccionable por palabra - transformando eficazmente toda la memoria en una matriz
muy grande. Entonces, si tenemos una direcci�n, el sistema provee una operaci�n
para recuperar el valor almacenado en la unidad de memoria en esa direcci�n (por lo
general la utilizaci�n de registros de prop�sito general de la m�quina).

En el caso usual, un puntero es lo suficientemente grande como para contener m�s


direcciones que no sean unidades de memoria en el sistema. Esto introduce la
posibilidad de que un programa puede intentar acceder a una direcci�n que
corresponde a ninguna unidad de memoria, ya sea porque no hay suficiente memoria
instalada (es decir, m�s all� del rango de memoria disponible) o porque la
arquitectura no soporta dichas direcciones. En el primer caso, en ciertas
plataformas como la arquitectura x86 de Intel, se llama un fallo de segmentaci�n
(violaci�n de segmento). El segundo caso es posible en la actual aplicaci�n de
AMD64, donde los punteros son de 64 bits de largo y direcciones solo se extienden a
48 bits. All�, punteros deben ajustarse a ciertas normas can�nicas (direcciones),
as� que si un puntero no can�nica se eliminan las referencias, el procesador
plantea un error de protecci�n general.

Por otra parte, algunos sistemas tienen m�s unidades de memoria que no son
direcciones. En este caso, se emplea un esquema m�s complejo, tal como la
segmentaci�n de memoria o de paginaci�n a utilizar diferentes partes de la memoria
en diferentes momentos. Las �ltimas encarnaciones de la arquitectura x86 soportan
hasta 36 bits de direcciones de memoria f�sica, que fueron asignadas al espacio de
direcciones lineal de 32 bits usando un mecanismo PAE de paginaci�n. As�, solo el
1/16 de la posible memoria total puede ser accedida a la vez. Otro ejemplo de la
misma familia de ordenadores estaba el modo protegido de 16 bits del procesador
80286, que, sin embargo, soportaba solamente 16 MiB de memoria f�sica, pudiendo
acceso a un m�ximo de 1 GiB de memoria virtual, pero la combinaci�n de direcci�n de
16 bits y el segmento de registros hizo acceder a m�s de 64 KiB en una estructura
de datos engorroso. Algunas restricciones de la aritm�tica del puntero ANSI
pudieron haberse debido a los modelos de memoria segmentadas de esta familia de
procesadores. [cita requerida]

Con el fin de proporcionar una interfaz consistente, algunas arquitecturas


proporcionan E/S mapeada en memoria, lo que permite a algunas direcciones que se
refieren a las unidades de memoria, mientras que otros se refieren a los registros
de dispositivos de otros dispositivos en el ordenador. Hay conceptos an�logos tales
como desplazamientos de archivo, los �ndices de matriz, y las referencias a objetos
remotos que sirven algunos de los mismos prop�sitos que las direcciones de otros
tipos de objetos.
Usos

Los punteros son compatibles directamente sin restricciones en lenguajes como PL/1,
C, C++, Pascal, y la mayor�a de los lenguajes ensambladores. Se utilizan
principalmente para la construcci�n de referencias, que a su vez son fundamentales
para la construcci�n de casi todas las estructuras de datos, as� como para pasar
datos entre las diversas partes de un programa.

En los lenguajes de programaci�n funcionales que dependen en gran medida de las


listas, los punteros y referencias son gestionados de manera abstracta por el
lenguaje utilizando construcciones internas como const.

Cuando se trata de matrices, la cr�tica operaci�n de b�squeda suele implicar un


c�lculo de direcci�n etapa llamada que implica la construcci�n de un puntero al
elemento de datos deseado en la matriz. Si los elementos de datos en la matriz
tienen longitudes que son divisibles por potencias de dos, esta aritm�tica es por
lo general un poco m�s eficiente.[cita requerida] El relleno generalmente es usado
como un mecanismo para asegurar que este sea el caso, a pesar del aumento de los
requerimientos de memoria. En otras estructuras de datos, tales como las listas
enlazadas, los punteros se utilizan como referencias para vincular de forma
expl�cita una sola pieza de la estructura a otra.

Los punteros se utilizan para pasar par�metros por referencia. Esto es �til si el
programador quiere modificaciones de una funci�n a un par�metro sea visible para
llamador de la funci�n de la funci�n. Esto tambi�n es �til para devolver varios
valores de una funci�n.

Los punteros tambi�n se puede utilizar para asignar y desasignar en la memoria


variables din�micas y matrices. Ya que muchas veces una variable puede volverse
redundante despu�s de que haya cumplido su objetivo, que resulta en una p�rdida de
la memoria mantenerla, en consecuencia es una buena pr�ctica para desasignarla
cuando ya no se necesita, utilizando la referencia de puntero original. El no
hacerlo puede resultar en una p�rdida de memoria (donde la memoria libre disponible
va disminuyendo gradualmente, o en casos severos r�pidamente, a causa de una
acumulaci�n de numerosos bloques de memoria redundantes).
Punteros en C

La sintaxis b�sica para definir un puntero es:4?

int * ptr;
Esto declara ptr como el identificador de un objeto, de la siguiente forma:

puntero que apunta a un objeto de tipo int

Esto usualmente se manifiesta de forma m�s sucinta como 'ptr es un puntero a int.'

Debido a que el lenguaje C no especifica una inicializaci�n impl�cita para los


objetos de duraci�n autom�tica de almacenamiento,5? frecuentemente se debe prestar
atenci�n para asegurarse de que la direcci�n a la que ptr puntea es v�lida; por eso
a veces se sugiere que un puntero pueda ser expl�citamente inicializado al valor de
puntero nulo, que es tradicionalmente especificado en C con la macro estandarizado
NULL:6?

int *ptr = NULL;

Desreferenciar un puntero nulo en C produce un comportamiento indefinido,7? que


podr�a ser catastr�fico. Sin embargo, la mayor�a de las implementaciones [cita
requerida], simplemente detienen la ejecuci�n del programa en cuesti�n, usualmente
con un fallo de segmentaci�n.

Sin embargo, punteros inicializados podr�a obstaculizar innecesariamente el


an�lisis del programa, ocultando de ese modo los bugs.

En cualquier caso, una vez que un puntero ha sido declarado, el siguiente paso
l�gico es que se apunte a algo:

int a = 5;
int *ptr = NULL;

ptr = &a;

Esto asigna el valor de la direcci�n de a a ptr. Por ejemplo, si a est� almacenado


en la ubicaci�n de memoria de 0x8130 entonces el valor de ptr ser� 0x8130 despu�s
de la asignaci�n. Para eliminar la referencia al puntero, se utiliza de nuevo el
asterisco:

*ptr = 8;

Esto significa tomar el contenido de ptr (que es 0x8130), "localizar" la direcci�n


en memoria y establecer su valor en 8. Si, m�s tarde, se accede de nuevo, su nuevo
valor ser� 8.

Este ejemplo puede ser m�s claro si la memoria no es directamente examinada.


Supongamos que a se localiza en la direcci�n 0x8130 en memoria y ptr en 0x8134;
tambi�n asume de que se trata de un equipo de 32 bits de tal manera que un int
tiene un ancho de 32 bits. Lo que sigue es lo que estar�a en la memoria despu�s de
que se ejecuta el siguiente fragmento de c�digo:

int a = 5;
int *ptr = NULL;

Direcci�n Contenido
0x8130 0x00000005
0x8134 0x00000000

(El puntero NULL que se muestra aqu� es 0x00000000.) Mediante la asignaci�n la


direcciona de a a ptr:

ptr = &a;
produce los siguientes valores de memoria:

Direcci�n Contenido
0x8130 0x00000005
0x8134 0x00008130

Entonces desreferenciando ptr mediante codificaci�n:

*ptr = 8;

la computadora tendr� el contenido de ptr (que es 0x8130), 'localizado' esa


direcci�n, y asignar 8 a esa ubicaci�n produciendo la siguiente memoria:

Direcci�n Contenido
0x8130 0x00000008
0x8134 0x00008130

Claramente, el acceso a a producir� el valor de 8 porque la instrucci�n anterior


modific� el contenido de a por medio del puntero ptr.
Matrices de C

En C, la indizaci�n de matrices se define formalmente en t�rminos de punteros


aritm�ticos, es decir, la especificaci�n del lenguaje requiere que array[i] sea
equivalente a *(array + i).8? As�, en C, las matrices pueden ser consideradas como
punteros a �reas de memoria consecutivas (sin espacios vac�os), [8] y la sintaxis
para acceder a las matrices es id�ntica a la cual se puede utilizar para
desreferenciar punteros. Por ejemplo, una matriz array puede ser declarada y
utilizada de la siguiente manera:

int array[5]; /* Declara 5 enteros contiguos */


int *ptr = array; /* Las matrices pueden ser utilizadas como punteros */
ptr[0] = 1; /* Los punteros se pueden indexar con la sintaxis de matrices */
*(array + 1) = 2; /* Las matrices pueden ser dereferenciadas con sintaxis de
puntero */
*(1 + array) = 3; /* La adici�n del puntero es conmutativa */
2[array] = 4; /* El operador sub�ndice es conmutativo */

Esto asigna un bloque de cinco enteros y nombres de la matriz de bloques, que act�a
como un puntero al bloque. Otro uso com�n de los punteros es para que apunte a la
memoria asignada din�micamente desde malloc que devuelve un bloque consecutivo de
memoria de no menos que el tama�o solicitado que se puede utilizar como una matriz.

Aunque la mayor�a de los operadores sobre matrices y punteros sean equivalentes, es


importante tener en cuenta que el operador sizeof ser� diferente. En este ejemplo,
sizeof (array) evaluar� a 5*sizeof(int) (el tama�o de la matriz), mientras que
sizeof(ptr) evaluar� sizeof (int*), el tama�o del propio puntero.

Los valores por defecto de una matriz se pueden declarar como:

int array[5] = {2,4,3,1,5};

Si se asume que array se encuentra en la memoria a partir de la direcci�n 0x1000 de


una m�quina little endian de 32 bits entonces la memoria contendr� lo siguiente
(los valores se encuentran en hexadecimal, as� como las direcciones):

0 1 2 3
1000 2 0 0 0
1004 4 0 0 0
1008 3 0 0 0
100C 1 0 0 0
1010 5 0 0 0

Aqu� est�n representados cinco enteros: 2, 4, 3, 1 y 5. Estos cinco enteros ocupan


32 bits (4 bytes) cada uno con el byte menos significativo que se almacena primero
(esto es una arquitectura de CPU little endian) y se almacenan de forma consecutiva
comenzando en la direcci�n 0x1000.

La sintaxis de C con punteros es:

array significa 0x1000


array+1 significa 0x1004 (tener en cuenta que en realidad significa el "1"
a�ade una vez el tama�o de un int (4 bytes) no literalmente "m�s uno")
*array significa desreferenciar los contenidos de array. Teniendo en cuenta el
contenido como una direcci�n de memoria (0x1000), buscar el valor en esa ubicaci�n
(0x0002).
array[i] significa n�mero de elemento i, base 0, de la matriz que se traduce en
*(array + i)

El �ltimo ejemplo es c�mo acceder a los contenidos del array. Descomponi�ndolo:

array + i es la posici�n de memoria de la (i +1)-�simo elemento de la matriz


*(array + i) toma esa direcci�n de memoria y elimina referencias a acceder al
valor.

Por ejemplo array[3] es sin�nimo de *(array+ 3), es decir, *(0x1000 + 3*sizeof


(int)), que dice "eliminar la referencia al valor almacenado en 0x100C", en este
caso 0x0001.
Lista vinculada en C

A continuaci�n se muestra un ejemplo de definici�n de una lista enlazada en C.

/* la lista enlazada vac�a est� representada por NULL


* o alg�n otro valor centinela */
#define EMPTY_LIST NULL

struct link {
void *datos; /* datos de este v�nculo */
struct link *proximo; /* siguiente enlace; EMPTY_LIST si no hay ninguno */
};

N�tese que esta definici�n puntero-recursivo es esencialmente la misma que la


definici�n de referencia-recursiva del lenguaje de programaci�n Haskell:

data Link a = Nil


| Cons a (Link a)

Nil es la lista vac�a y Cons a (Link a) es una cons cell de un tipo a con otro
enlace tambi�n de tipo a.

Sin embargo, la definici�n de referencias es de tipo comprobado y no utiliza los


valores de se�al potencialmente confusos. Por esta raz�n, en C, las estructuras de
datos normalmente se tratan a trav�s de funciones contenedor, que son
cuidadosamente verificadas para su correcci�n.
Pasaje por direcci�n utilizando punteros

Los punteros se pueden usar para pasar variables por su direcci�n, lo que permite
cambiar su valor. A modo de ejemplo, se considera el siguiente c�digo en C:
#include <stdio.h>
/* se puede cambiar una copia de int n dentro de la funci�n sin afectar el c�digo
de llamada */
void passbyvalue(int n) {
n = 12;
}

/* En su lugar, se pasa un puntero a m. No se crea ninguna copia m de s� mismo */


void passbyaddress(int *m) {
*m = 14;
}

int main(void) {
int x = 3;

/* pasar una copia del valor de x como argumento */


passbyvalue(x);
// el valor ha cambiado dentro de la funci�n, pero x sigue siendo 3 de aqu�
posteriormente

/* pasar la direcci�n de x como argumento */


passbyaddress(&x);
// en realidad x fue cambiada por la funci�n y ahora aqu� es igual a 14

return 0;
}

Asignaci�n din�mica de memoria

Los punteros se utilizan para almacenar y administrar las direcciones de los


bloques de memoria asignados din�micamente. Dichos bloques se utilizan para
almacenar objetos o conjuntos de objetos de datos. Los lenguajes m�s estructurados
y orientados a objetos proporcionan un �rea de memoria, llamada el mont�n o tienda
libre, de la que objetos din�micamente asignados.

El c�digo de ejemplo C siguiente ilustra c�mo se asignan din�micamente objetos de


estructura y referencia. La biblioteca C est�ndar proporciona la funci�n malloc()
para asignar bloques de memoria desde el mont�n. Se necesita el tama�o de un objeto
para asignarlo como par�metro y devolver un puntero a un bloque reci�n asignado de
memoria adecuado para almacenar el objeto, o se devuelve un puntero nulo si la
asignaci�n falla.

/* Item de inventario de partes */


struct Item {
int id; /* N�mero de parte */
char * name; /* Nombre de parte */
float cost; /* Costo */
};

/* Asignar e inicializar un nuevo objeto de elemento */


struct Item * make_item(const char *name) {
struct Item * Item;

/* Asignar un bloque de memoria para un nuevo objeto de elemento */


Item = (struct Item *)malloc(sizeof(struct Item));
if (Item == NULL)
return NULL;
/* Inicializa los miembros del nuevo elemento */
memset(Item, 0, sizeof(struct Item));
Item->id = -1;
Item->name = NULL;
Item->cost = 0.0;

/* Guarde una copia del nombre en el nuevo elemento */


Item->name = (char *)malloc(strlen(name) + 1);
if (Item->name == NULL) {
free(Item);
return NULL;
}
strcpy(Item->name, name);

/* Devuelve el objeto de art�culos recientemente creados */


return Item;
}

El c�digo siguiente muestra c�mo se desasignan din�micamente objetos de memoria, es


decir, retorna al mont�n o tienda libre. La biblioteca C est�ndar proporciona la
funci�n free() para cancelar la asignaci�n de un bloque de memoria previamente
asignado y retornar de nuevo al mont�n.

/* Desasignar un objeto Item */


void destroy_item(struct Item *item) {
/* Check for a null object pointer */
if (item == NULL)
return;

/* Desasignar la cadena de nombre guardado en el Item */


if (item->name != NULL) {
free(item->name);
item->name = NULL;
}

/* Desasignar el propio objeto Item */


free(item);
}

Hardware asignado en memoria

En algunas arquitecturas de computaci�n, los punteros pueden ser utilizados para


manipular directamente de memoria o dispositivos asignados a la memoria.

La asignaci�n direcciones a los punteros es una herramienta invaluable en la


programaci�n de microcontroladores. A continuaci�n se muestra un simple ejemplo de
declaraci�n de un puntero de tipo int y la inicializaci�n a una direcci�n
hexadecimal en este ejemplo el constante 0x7FFF:

int *hardware_address = (int *)0x7FFF;

A mediados de los a�os 80, usar la BIOS para acceder a las capacidades de video de
PC era lento. Las aplicaciones que se encontraban en pantalla intensiva normalmente
se utiliza para acceder a la memoria de v�deo CGA directamente mediante colada las
constantes hexadecimales 0xb8000 a un puntero a un array de 80 valores int de 16
bits sin signo. Cada valor consist�a en un c�digo ASCII en el byte bajo y un color
en el byte alto. Por lo tanto, para poner la letra 'A' en la l�nea 5, columna 2
blanco sobre azul luminoso, uno podr�a escribir c�digo como el siguiente:
#define VID ((unsigned short (*)[80])0xB8000)

void foo() {
VID[4][1] = 0x1F00 | 'A';
}

Punteros con tipo y fundici�n

En muchos lenguajes, los punteros tienen la restricci�n adicional de que el objeto


que apuntan tiene un tipo espec�fico. Por ejemplo, un indicador puede ser declarado
para apuntar a un n�mero entero; ser� el lenguaje el que trate de evitar que el
programador apunte a objetos que no fuesen n�meros enteros, tales como n�meros de
coma flotante, eliminando algunas errores.

Por ejemplo, en C

int *money;
char *bags;

money ser�a un puntero entero y bags ser�a un puntero char. Lo siguiente dar�a una
advertencia del compilador de "asignaci�n desde un tipo de puntero" bajo GCC

bags = money;

porque money y bags fueron declarados con diferentes tipos. Para suprimir la
advertencia del compilador, debe quedar expl�cita de que realmente se desea hacer
la cesi�n por encasillamiento.

bags = (char *)money;

que dice emitir el puntero entero de money a un puntero char y asignarlo a bags.

Un proyecto de la norma C est�ndar de 2005 requiere que echando un puntero derivado


de un tipo a uno de otro tipo deb�a mantener la correcci�n de alineaci�n para ambos
tipos (6.3.2.3 Punteros, par 7):9?

char *external_buffer = "abcdef";


int *internal_data;

internal_data = (int *)external_buffer; // COMPORTAMIENTO INDEFINIDO si "el


puntero resultante
// no est� correctamente alineado"

En lenguajes que permiten la aritm�tica de punteros, dicha aritm�tica en punteros


tiene en cuenta el tama�o del tipo. Por ejemplo, la adici�n de un n�mero entero a
un puntero produce otro puntero que apunta a una direcci�n que es superior en
n�mero de veces que el tama�o del tipo. Esto nos permite calcular f�cilmente la
direcci�n de elementos de una matriz de un tipo determinado, como se demostr� en el
ejemplo matrices C descripto arriba. Cuando un puntero de un tipo se convierte en
otro tipo de un tama�o diferente, el programador debe esperar que el puntero
aritm�tico se calcule de manera diferente. En C, por ejemplo, si la matriz money
comienza a 0x2000 y sizeof (int) es 4 bytes mientras que sizeof (char) es de 1
byte, entonces (money+1) apuntar� a 0x2004 pero (bags+1) apuntar� a 0x2001. Entre
otros riesgos de la fundici�n se incluyen la p�rdida de datos, cuando los datos
"anchos" se escribe en ubicaciones "estrechas" (por ejemplo, bags[0] = 65537;), se
obtienen resultados inesperados cuando hay valores de desplazamiento de bits, y
problemas de comparaci�n, sobre todo entre valores con signo vs valores sin signo.

Aunque por lo general sea imposible determinar en tiempo de compilaci�n que arroja
son seguros, algunos lenguajes almacenan el tipo de informaci�n en tiempo de
ejecuci�n que puede ser utilizado para confirmar que estos peligrosos moldes son
v�lidos en tiempo de ejecuci�n. Otros lenguajes simplemente aceptan una
aproximaci�n conservadora de moldes seguros, o ninguno en absoluto.
Haciendo m�s seguros a los punteros
El texto que sigue es una traducci�n defectuosa.
Si quieres colaborar con Wikipedia, busca el art�culo original y mejora esta
traducci�n.
Copia y pega el siguiente c�digo en la p�gina de discusi�n del autor: {{subst:Aviso
mal traducido|Puntero (inform�tica)}} ~~~~

Como un puntero permite que un programa intente acceder a un objeto que puede no
estar definido, dichos punteros pueden ser el origen de una variedad de errores de
programaci�n. Sin embargo, la utilidad de los punteros es tan grande que puede ser
dif�cil realizar tareas de programaci�n sin ellos. En consecuencia, muchos
lenguajes han creado construcciones dise�adas para proporcionar algunas de las
caracter�sticas �tiles de los punteros sin algunas de sus trampas, tambi�n
denominadas algunas veces peligros de punteros. En este contexto, los punteros que
se dirigen directamente a la memoria (como se usa en este art�culo) se conocen como
punteros crudos o sin procesar, en contraste con punteros inteligentes u otras
variantes.

Uno de los mayores problemas con los punteros es que al poderse manipular
directamente como un n�mero, se pueden hacer que este apunte a direcciones no
utilizadas o a datos que se est� utilizando para otros fines. Muchos lenguajes,
incluyendo lenguajes de programaci�n funcionales y los �ltimos lenguajes
imperativos como Java, reemplazan los punteros con un tipo m�s opaco de referencia,
t�picamente referido simplemente como referencia, que solo puede ser usado para
referirse a los objetos y no manipula a los n�meros, previniendo este tipo de
error. La indexaci�n de una matriz se trata como un caso especial.

Un puntero que no tenga ninguna direcci�n asignada al mismo se denomina puntero


salvaje. Cualquier intento de utilizar estos punteros no inicializados puede causar
un comportamiento inesperado, ya sea porque el valor inicial no es una direcci�n
v�lida, o porque su uso puede da�ar otras partes del programa. El resultado suele
ser un fallo de segmentaci�n, violaci�n de almacenamiento o rama natural (si se
utiliza como un puntero de funci�n o de direcci�n de rama).

En sistemas con asignaci�n de memoria expl�cita, es posible crear un puntero de


referencia colgante para des-asignar la direcci�n de memoria que apunta dentro.
Este tipo de puntero es peligroso y sutil, ya una regi�n de memoria des-asignada
puede contener los mismos datos como lo hizo antes de que se cancele la asignaci�n,
pero puede ser reasignado a continuaci�n y se sobrescriben con c�digo ajeno,
desconocido para el c�digo anterior. Los lenguajes con recolector de basura
previenen este tipo de error porque des afectaci�n se realiza autom�ticamente
cuando no hay m�s referencias en el alcance.

Algunos lenguajes, como C++, soportan punteros inteligentes, que utilizan una forma
simple de conteo de referencias con el fin de ayudar a la asignaci�n de un registro
de la memoria din�mica, adem�s de actuar como referencia. En la ausencia de ciclos
de referencia, donde un objeto se auto refiere indirectamente mediante una
secuencia de punteros inteligentes, �stos eliminan la posibilidad de punteros
colgantes y p�rdidas de memoria. Las cadenas en Delphi soportan, de forma nativa,
recuento de referencias.
Puntero nulo

Un puntero nulo tiene un valor reservado para indicar que el puntero no se refiere
a un objeto v�lido. Los punteros nulos se utilizan habitualmente para representar
las condiciones tales como el final de una lista de longitud desconocida o el
fracaso para llevar a cabo alg�n tipo de acci�n, lo que el uso de punteros nulos se
puede comparar con los tipos que aceptan valores NULL y el valor de nada en un tipo
de opci�n.

Frecuentemente, los punteros nulos se consideran similares a los valores nulos en


las bases de datos relacionales, pero tienen una sem�ntica algo diferente. En la
mayor�a de los lenguajes de programaci�n, un puntero nulo significa "ning�n valor",
mientras que en una base de datos relacional, un valor nulo significa "valor
desconocido". Esto conduce a importantes diferencias en la pr�ctica: en la mayor�a
de los lenguajes de programaci�n consideran iguales dos punteros nulos se, pero no
lo son dos valores nulos en las bases de datos relacionales (no se sabe si son
iguales, ya que representan valores desconocidos).

En algunos entornos de lenguaje de programaci�n (al menos, por ejemplo, una


implementaci�n de Lisp propietaria[cita requerida]), el valor utilizado como
puntero nulo (llamado nil en Lisp) puede, en realidad, ser un puntero a un bloque
de datos internos de utilidad para la aplicaci�n (pero no accesible expl�citamente
desde los programas de usuario), permitiendo as� que el mismo registro sea
utilizado como una constante �til y una forma r�pida de acceder a partes internas
de aplicaci�n. Esto se conoce como vector nil (�nulo�).

En C, dos punteros nulos de cualquier tipo est�n garantidos para comparar iguales
tipo de datos10? El macro NULL es una implementaci�n definida por una constante de
puntero NULL,6? que en C99 se puede expresar portablemente como un valor entero 0
convertido impl�cita o expl�citamente al tipo void*.11?

T�picamente, desreferenciar el puntero NULL significa intentar leer o escribir en


la memoria que no se asigna, esto desencadena un fallo de segmentaci�n o violaci�n
de acceso. Esto puede representar en s� mismo, para el desarrollador, un fallo en
el programa, o se transforma en una excepci�n que puede capturarse. Sin embargo,
hay ciertas circunstancias en las que esto no es el caso. Por ejemplo, en modo en
x86 real, la direcci�n 0000:0000 es legible y por lo general escribible, de ah� que
la eliminaci�n de referencias de puntero nulo sea una acci�n perfectamente v�lida
pero, en general, no deseada que puede conducir a un comportamiento indefinido,
pero no causa un crash en la aplicaci�n. Adem�s, tener en cuenta que hay ocasiones
en que la desreferenciaci�n NULL es intencional y bien definida, como por ejemplo
el c�digo del BIOS, escrito en C, para dispositivos x86 de 16 bits en modo real,
puede escribir la IDT en la direcci�n f�sica 0 de la m�quina, desreferenciando al
puntero a NULL para la escritura. Tambi�n es posible que el compilador optimice
desde lejos el puntero de dereferencia `NULL`, evitando un fallo de segmentaci�n
pero sin causar otro tipo de comportamiento no deseado.

En C++, ya que el macro NULL fue heredado de C, tradicionalmente se prefere el


literal entero para cero para representar una constante de puntero nulo.12? Sin
embargo, C++11 ha introducido una constante nullptr expl�cita que se utilizar� en
su lugar.

No se debe confundir un puntero nulo con un puntero no inicializado: Un puntero


nulo est� garantizado para comparar desigual a cualquier puntero que apunta a un
objeto v�lido. Sin embargo, en funci�n del idioma y la aplicaci�n, un puntero no
inicializado tiene, o bien un valor indeterminado (al azar o sin sentido), o un
valor espec�fico que no tiene por que ser necesariamente una especie de puntero
nulo constante.

En 2009, C. A. R. Hoare declar�13?14? que en 1965 invent� la referencia nula como


parte del lenguaje Algol W, aunque, desde 1959, NIL hubiera existido en Lisp. En
esa referencia de 2009 Hoare describe su invenci�n como un "error de millones de
d�lares":
A mi error yo lo llamo error de mil millones de d�lares. Fue la invenci�n, en
1965, de la referencia nula. En ese momento, yo estaba dise�ando el primer sistema
de tipo integral para las referencias en un lenguaje orientado a objetos (ALGOL W).
Mi objetivo era asegurar que todo uso de referencias debe ser absolutamente
seguras, con la comprobaci�n realizada autom�ticamente por el compilador. Pero no
pude resistir la tentaci�n de poner en una referencia nula, simplemente porque era
muy f�cil de implementar. Esto ha dado lugar a innumerables errores,
vulnerabilidades y fallos del sistema, que probablemente han causado mil millones
de d�lares de dolor y da�os en los �ltimos cuarenta a�os.

Debido a que un puntero nulo no apunta a un objeto significativo, por lo general,


(pero no siempre) intentar eliminar la referencia a un puntero nulo provoca un
error en tiempo de ejecuci�n o la inmediata ca�da del programa.

En C, no est� definido el comportamiento de eliminaci�n de referencias a un


puntero nulo15? Muchas implementaciones causan este tipo de c�digo de lugar a que
el programa se detenga con una violaci�n de acceso, porque se elige la
representaci�n de puntero nulo para ser una direcci�n que no es asignada por el
sistema para el almacenamiento de objetos. Sin embargo, este comportamiento no es
universal.
En Java, acceder a una referencia nula desencadena una NullPointerException
(NPE), que puede detectar el c�digo de gesti�n de errores, pero en la pr�ctica lo
que se prefiere es asegurar que nunca ocurran tales excepciones.
En. NET, acceder a la referencia nula desencadena una excepci�n
NullReferenceException. Aunque generalmente la captura de �stos se considera una
mala pr�ctica, se puede atrapar este tipo de excepci�n y manipularse por el
programa.
En Objective-C, los mensajes se pueden enviar a un objeto nil (que es
esencialmente un puntero nulo) sin causar que el programa se interrumpa; el mensaje
es simplemente ignorado, y el valor de retorno (si lo hay) es nil o 0, dependiendo
del tipo.16?

En lenguajes con una arquitectura de etiquetado, posiblemente, un puntero nulo


pueda ser reemplazado con una uni�n marcada que impone la manipulaci�n expl�cita
del caso excepcional, de hecho, un puntero nulo, posiblemente, pueda ser visto como
un puntero etiquetado con una etiqueta computarizada.
Puntero auto relativo

El t�rmino puntero auto relativo puede referirse a un puntero cuyo valor se


interpreta como un desplazamiento desde la direcci�n del propio puntero, por lo
que, si una estructura de datos, M {\displaystyle M} M, tiene un elemento puntero
auto relativo, p {\displaystyle p} p, que apunta a una porci�n M {\displaystyle M}
M de s� mismo, entonces M {\displaystyle M} M puede ser reubicado en la memoria sin
tener que actualizar el valor de p {\displaystyle p} p.17? La patente citada
tambi�n utiliza el t�rmino puntero auto relativo para significar la misma cosa. Sin
embargo, el significado de ese t�rmino se ha utilizado en otras formas:

Es de uso frecuente significar un desplazamiento de la direcci�n de una


estructura y no de la direcci�n de la propia puntero.[cita requerida]
Se ha utilizado para significar un puntero que contiene su propia direcci�n,
que puede ser �til para la reconstrucci�n en cualquier regi�n arbitraria de la
memoria una colecci�n de estructuras de datos que apuntan la una a la otra.18?

Puntero base

Un puntero base es un puntero cuyo valor es un desplazamiento desde el valor de


otro puntero. Esto puede ser usado para almacenar y cargar los bloques de datos,
asignando la direcci�n de comienzo del bloque al puntero base.19?
Indirecci�n m�ltiple
En algunos lenguajes, un puntero puede hacer referencia a otro puntero, lo que
requiere m�ltiples operaciones de des referenciaci�n para llegar al valor original.
Mientras que cada nivel de indirecci�n puede a�adir un costo de rendimiento, es a
veces necesario para proporcionar un comportamiento correcto para estructuras de
datos complejas. Por ejemplo, en C es t�pico definir una lista enlazada, en
t�rminos de un elemento que contiene un puntero al siguiente elemento de la lista:

struct element
{
struct element * next;
int value;
};

struct element * head = NULL;

Esta aplicaci�n utiliza un puntero al primer elemento de la lista como un sustituto


para la lista completa. Si se a�ade un nuevo valor al principio de la lista, debe
cambiarse la cabecera para que apunte al nuevo elemento. Dado que argumentos C
siempre se pasan por valor, utilizando direccionamiento indirecto doble se permite
la inserci�n de implementarse correctamente, y tiene el efecto secundario deseable
de eliminar el c�digo de casos especiales para hacer frente a las inserciones en la
parte delantera de la lista:

// Dada una lista ordenada en la * cabecera, insertar el elemento elemento en la


primera
// lugar donde todos los elementos anteriores tienen menor o igual valor.
void insert(struct element **head, struct element *item)
{
struct element ** p; // p apunta a un puntero de un elemento

for (p = head; *p != NULL; p = &(*p)->next)


{
if (item->value <= (*p)->value)
break;
}
item->next = *p;
*p = item;
}

// El llamador hace esto:


insert(&head, item);

En este caso, si el valor de item es menor que el de la head, se actualizar� el


llamador head, correctamente a la direcci�n del nuevo item.

Un ejemplo b�sico es en el argumento argv de la funci�n principal en C (y C ++),


que se da en el prototipo como char **argv - esto es debido a que la variable argv
es en s� es un puntero a un arreglo de cadenas (un arreglo de arreglos), por lo que
*argv es un puntero a la cadena 0 (por convenci�n al nombre del programa), y **argv
es el car�cter 0 de la cadena 0.
Puntero a funci�n

En algunos lenguajes, un puntero puede hacer referencia a c�digo ejecutable, es


decir, puede apuntar a una funci�n, m�todo o procedimiento. Un puntero a funci�n
almacenar� la direcci�n de una funci�n que sea invoca. Si bien este mecanismo se
puede utilizar para llamar a funciones de forma din�mica, muchas veces es una
t�cnica favorita de virus y otros autores de software malicioso.
int a, b, x, y;
int sum(int n1, int n2); // Funci�n con dos par�metros enteros que devolvie
un valor entero
int (*fp)(int, int); // Puntero de funci�n que puede apuntar a una
funci�n como la suma

fp = &sum; // fp ahora apunta a la funci�n suma


x = (*fp)(a, b); // La funci�n suma llama con argumentos a y b
y = sum(a, b); // La funci�n suma llama con argumentos a y b

Puntero salvaje

Un puntero salvaje es un puntero que no se ha sido inicializado (es decir, un


puntero salvaje no ha tenido ninguna direcci�n asignada a �l) y puede provocar un
fallo en el programa o comportarse de manera extra�a. En los lenguajes de
programaci�n Pascal o C, los punteros que no est�n espec�ficamente inicializados
pueden apuntar a direcciones impredecibles en la memoria.

El siguiente c�digo de ejemplo muestra un puntero salvaje:

int func(void)
{
char *p1 = malloc(sizeof(char)); /* (valor (indefinido) de alg�n lugar del
mont�n */
char *p2; /* puntero salvaje (sin inicializar) */
*p1 = 'a'; /* Esto est� bien, asumiendo que malloc() no haya devuelto
NULL. */
*p2 = 'b'; /* As� se invoca un comportamiento indefinido */
}

Aqu�, p2 puede apuntar a cualquier lugar de la memoria, por lo que la realizaci�n


de la tarea * p2 = 'b' puede corromper una zona desconocida de la memoria o
provocar un fallo de segmentaci�n.
Simulaci�n utilizando un �ndice de matriz

Es posible simular el comportamiento del puntero usando un �ndice a un matriz


(normalmente unidimensional)

Principalmente para lenguajes que no soportan punteros de manera expl�cita pero


realizan soporte de matrices, la matriz se puede considerar y procesar como si
fuera el rango de memoria completo (dentro del alcance de la matriz particular) y
cualquier �ndice a ella puede considerarse como equivalente a un registro de
prop�sito general en lenguaje ensamblador (que apunta a los bytes individuales pero
cuyo valor real es relativo al comienzo de la matriz, no su direcci�n absoluta en
memoria). Suponiendo que la matriz es, por ejemplo, una estructura de datos de
caracteres contiguos de 16 megabytes, los bytes individuales (o una cadena de bytes
contiguos dentro de la matriz) puede ser directamente dirigida y manipulada usando
el nombre de la matriz con un entero sin signo de 31 bits como el puntero simulado
(esto es bastante similar al ejemplo de arreglos de C mostrado anteriormente). La
aritm�tica de punteros puede simularse mediante la adici�n o sustracci�n del
�ndice, con una sobrecarga adicional m�nima en comparaci�n con la verdadera
aritm�tica de punteros.

Incluso es te�ricamente posible, utilizando la t�cnica anterior, juntar con un


simulador de juego de instrucciones adecuadas para simular cualquier c�digo de
m�quina o el intermedio (bytescode) de cualquier procesador/lenguaje en otro
lenguaje que no admite punteros en absoluto (por ejemplo Java / JavaScript). Para
lograr esto, el c�digo binario se puede cargar inicialmente en los bytes contiguos
de la matriz para que el simulador "lea", interprete y se ejecute enteramente
dentro de la memoria contenida de la misma matriz. Si es necesario, generalmente se
puede activar comprobaci�n de l�mites por el compilador, a los efectos de evitar
por completo los problemas de desbordamiento de b�fer (o si no, codificar a mano en
el simulador).
Punteros en lenguajes de programaci�n

En programaci�n es posible crear procedimientos, estructuras, variables, constantes


entre otras cosas, cuando es ejecutada cada una de estas estructuras tiene una
direcci�n en memoria, es conveniente conocer este tipo de informaci�n cuando se
trabaja con lenguajes que soportan los punteros de manera no abstracta.

A continuaci�n veremos c�mo trabajan los punteros en variables, estructuras y


uniones. Los punteros que apunten a estas estructuras de almacenamiento estar�n
dirigidos a los primeros miembros de cada estructura, uni�n o matriz.
Estructuras

Las estructuras de datos reservan segmentos en memoria separados para cada miembro,
esto significa que cada miembro tiene su propia direcci�n en memoria (su propio
puntero).

Podemos representar gr�ficamente una estructura de datos llamada "Estructura" de la


siguiente manera:

1 1 4 Bytes.
+-----+-----+---------+
| A | B | C | Miembros.
+-----+-----+---------+
0x1 0x2 0x3 Direcci�n.
^
|
Puntero base de la estructura completa.

Como se puede ver, existen 3 m�todos de tipo num�rico en memoria llamados "A","B" y
"C", los dos primeros m�todos (A y B) son de tipo Byte y tienen reservado 1 byte
cada uno en distintos segmentos en la memoria, por lo que tienen diferentes
direcciones (0x01 y 0x02 en su respectivo orden).

La direcci�n de memoria de la estructura en general es igual a la direcci�n de su


primer miembro, la direcci�n de su segundo miembro es igual a la direcci�n de su
primer miembro, mas su tama�o en bytes y la direcci�n del tercer miembro es igual a
la direcci�n del primer miembro, m�s el tama�o de los dos miembros anteriores y as�
sucesivamente.
Uniones

La principal diferencia entre una uni�n y una estructura es la memoria utilizada, a


diferencia de las estructuras, las uniones solo utilizan la cantidad de memoria de
su miembro m�s grande, y todos los miembros comparten una �nica direcci�n en
memoria.

Por ejemplo:

4 Bytes.
+-----------+
| A B C | Miembros.
+-----------+
0x1 Direcci�n.

Los miembros "A" y "C" solo pueden contener valores entre 0 y 255 (Tipo Byte), el
miembro "B" puede tener valores entre 0 y 4.294.967.295 (Tipo Entero), si el
miembro "A" cambia su valor a 13, tambi�n lo hacen los miembros "B" y "C" (A,B y C
son igual a 13), si el miembro "B" cambia su valor a 4000, los miembros "A" y "C"
se quedan �nicamente en 160 ya que tratan de traducir el valor 4000 a byte (A y C
son igual a 160, B = 4000), el tama�o total de la uni�n es de 4 bytes debido a que
los miembros comparten la misma memoria (la uni�n pesa lo mismo que su miembro con
mayor reserva de memoria).
Matrices

Las matrices son casi igual que las estructuras, reservan memoria para cada matriz,
la direcci�n en memoria de cada miembro es consecutiva a la suma de sus anteriores,
mas sus tama�os y la direcci�n de la matriz total es igual a la del primer miembro,
la �nica diferencia entre una matriz y una estructura es que cada matriz tiene el
mismo tipo de dato (los miembros de una estructura pueden ser de distintos tipos).

Podemos representar a una matriz con rango de 3 (tipo entero) en memoria de la


siguiente manera.

4 4 4 Bytes.
+-----+-----+-----+
| 0 | 1 | 2 | Identificador.
+-----+-----+-----+
0x1 0x5 0x9 Direcci�n.

Como se puede apreciar, cada miembro tiene una direcci�n en memoria con 4 bytes de
diferencia entre s�. El puntero base de la matriz entera es la direcci�n de su
primer matriz (Matriz@ = Matriz[0]@).
Soporte en lenguajes de programaci�n
Ada

Ada es un lenguaje fuertemente tipado en el cual todos los punteros son tipados y
solamente se permiten conversiones de tipos de seguros. Todos los indicadores est�n
por defecto inicializado en null, y cualquier intento de acceder a la informaci�n a
trav�s de un puntero a null provoca una excepci�n. En Ada, los punteros se llaman
tipos de acceso. Ada-83 no permit�a aritm�tica en tipos de acceso (aunque los
distintos compiladores la suministren como una funcionalidad fuera del patr�n),
pero Ada-95 soporta tipos aritm�ticos en tipos de acceso seguro por el paquete
System.Storage_Elements.
BASIC

Varias versiones antiguas de BASIC para la plataforma Windows ten�an soporte para
STRPTR() para devolver la direcci�n de una cadena, y para VARPTR() para devolver la
direcci�n de una variable. Visual Basic 5 tambi�n ten�a soporte para OBJPTR() para
devolver la direcci�n de una interfaz de objeto, y para un operador ADDRESSOF para
devolver la direcci�n de una funci�n. Los tipos de todos estos son n�meros enteros,
pero sus valores son equivalentes a estos valores por tipos de puntero.

Sin embargo, dialectos m�s recientes de BASIC, como FreeBASIC o BlitzMax, tienen
implementaciones de puntero exhaustivas. En FreeBASIC, la aritm�tica en punteros
ANY (equivalente al void* de C) son tratados como si el puntero ANY fuera un ancho
de bytes. A diferencia de C, los punteros ANY no pueden ser desreferenciados.
Adem�s, la conversi�n entre ANY y cualquier otro tipo de punteros no generar�
ninguna advertencia.

dim as integer f = 257


dim as any ptr g = @f
dim as integer ptr i = g
assert(*i = 257)
assert( (g + 4) = (@f + 1) )
C y C++

En C y C++ los punteros son variables que almacenan direcciones y pueden ser null.
Cada puntero tiene un tipo que apunta, pero el programador puede convertir
libremente entre tipos de puntero (pero no entre un puntero a funci�n y no la
funci�n de tipo de puntero). Un tipo de puntero especial llamado el "vac�o puntero"
permite que apunta a cualquier tipo de variable (no funci�n), pero es limitada por
el hecho de que no se puede eliminar las referencias de forma directa. La direcci�n
en s� a veces puede ser manipulada directamente mediante colada un puntero hacia y
desde un tipo entero de tama�o suficiente, aunque los resultados se han definido
por la implementaci�n y de hecho pueden causar un comportamiento indefinido;
mientras que los est�ndares anteriores a C no tengan un tipo entero que garantice
que sea lo suficientemente grande, C99 especifica el nombre definido uintptr_?
typedef en < stdint.h>, pero una aplicaci�n no tiene por qu� proporcionarla.

C++ es totalmente compatible con los punteros de C y el typecasting de C. Tambi�n


es compatible con una nueva agrupaci�n de operadores de typecasting para ayudar a
capturar a algunos casts peligrosos no deseados en tiempo de compilaci�n. Desde C+
+11, la librer�a est�ndar de C++ tambi�n proporciona punteros inteligentes
(unique_ptr, shared_ptr y weak_ptr) que se pueden utilizar en algunas situaciones
como una alternativa segura a los punteros primitivos de C. C++ tambi�n es
compatible con otro tipo de referencia, muy diferente de un puntero, llamado
simplemente una referencia o tipo de referencia.

La aritm�tica de punteros, es decir, la capacidad de modificar la direcci�n de


destino de un puntero con operaciones aritm�ticas (as� como comparaciones de
magnitud), est� restringido por el lenguaje est�ndar para permanecer dentro de los
l�mites de un solo objeto arreglo (o justo despu�s de �l), porque de otro modo
provocar�a un comportamiento indefinido. Sumando o restando de un puntero que
desplaza por un m�ltiplo del tama�o del tipo de datos que apunta. Por ejemplo, la
adici�n de 1 a un puntero a valores enteros de 4 bytes incrementar� el puntero por
4. Esto tiene el efecto de incrementar el puntero para se�alar en el siguiente
elemento en una matriz contigua de n�meros enteros-que muchas veces presenta un
resultado previsto. La aritm�tica de punteros no se puede realizar en punteros void
porque el tipo de vac�o no tiene tama�o, y por lo tanto no puede a�adir la
direcci�n de punteros, aunque gcc y otros compiladores realizan operaciones
aritm�ticas de byte de void* como una extensi�n no est�ndar. Para trabajar
"directamente" con bytes, generalmente arrojan punteros a BYTE*, o unsigned char*
si BYTE no est� definido en la biblioteca est�ndar que se utiliza.

La aritm�tica de punteros le provee al programador una �nica manera de tratar con


diferentes tipos: sumando y restando el n�mero de los elementos requeridos en lugar
del actual desplazamiento en bytes. (aunque el puntero sea char, el char se define
como tener siempre un tama�o de un byte, permite el desplazamiento del elemento de
la aritm�tica de punteros en la pr�ctica sea igual a un desplazamiento de bytes) En
particular, la definici�n C declara expl�citamente que la sintaxis de a[n], que es
el elemento n-�simo de la matriz de a, es equivalente a *(a+n), que es el contenido
del elemento apuntado por a+n. Esto implica que n[a] es equivalente a a[n], y se
puede escribir, por ejemplo, a[3] o 3[a] por igual para acceder al cuarto elemento
de una matriz a.

Aunque poderosa, la aritm�tica de punteros puede ser una fuente de errores


inform�ticos. Este tiende a confundir a los programadores novatos, forz�ndolos a
diferentes contextos: una expresi�n puede ser una aritm�tica ordinaria uno o una
aritm�tica de punteros uno, ya veces es f�cil confundir uno con el otro. En
respuesta a esto, muchas lenguajes inform�ticos modernos de alto nivel (por ejemplo
Java) no permiten el acceso directo a memoria utilizando direcciones. Adem�s, el
dialecto seguro de C, Cyclone, aborda muchos de los problemas con los punteros.
V�ase lenguaje de programaci�n C de examinar m�s.
El puntero void, o void*, es compatible en ANSI C y C++ como tipo de gen�rico
puntero. Un puntero a void puede almacenar una direcci�n a cualquier tipo de datos
no-funci�n, y, en C, se convierte impl�citamente a cualquier otro tipo de puntero
en asignaci�n, pero se debe convertir expl�citamente si es desreferenciado en
l�nea. K&R C utiliza char* para el prop�sito de "puntero de tipo agn�stico" (antes
de ANSI C).

int x = 4;
void* q = &x;
int* p = q; /* void* convierte impl�citamente a int*: v�lido en C, pero no en C++
*/
int i = *p;
int j = *(int*)q; /* cuando se desreferencia en l�nea, no hay conversi�n impl�cita
*/

C++ no permite la conversi�n impl�cita de void* a otros tipos de puntero, incluso


en las asignaciones. Esta fue una decisi�n de dise�o para evitar vaciados
descuidados e incluso no deseados, aunque la mayor�a de los compiladores solo
muestren advertencias como salida, no errores, cuando se encuentran con otros cast.

int x = 4;
void* q = &x;
// int* p = q; Esto falla en C++: no hay conversi�n impl�cita de void*
int* a = (int*)q; // cast estilo C
int* b = static_cast<int*>(q); // C++ cast

En C++, no hay void& y (referencia a void) para complementar void* (puntero a


void), ya que las referencias se comportan como alias a las variables que apuntan,
y nunca puede ser una variable cuyo tipo es void.
C#

En el lenguaje de programaci�n C#, los punteros son compatibles solo bajo ciertas
condiciones: cualquier bloque de c�digo que incluya punteros debe ser marcada con
la palabra clave unsafe. Generalmente, tales bloques requieren permisos de
seguridad superiores a c�digo pointerless que se le permitiera correr. La sintaxis
es esencialmente la misma que en C++, y la direcci�n apuntada se puede gestionar
tanto memoria administrada como no administrado. Sin embargo, los punteros a
memoria administrada (cualquier puntero a un objeto administrado) deben ser
declarado usando la palabra clave fixed, lo que evita que la recolector de basura
del movimiento del objeto apuntado, como parte de la gesti�n de memoria mientras el
puntero est� a su alcance, lo que mantiene v�lida la direcci�n del puntero.

Una excepci�n a esto es utilizar la estructura de IntPtr, que es un equivalente


administrado seguro para int*, y no requiere c�digo no seguro. Este tipo suele
aparecer cuando el uso de m�todos de las System.Runtime.InteropServices, por
ejemplo:

// Obtener 16 bytes de memoria de la memoria no administrada del proceso


IntPtr pointer = System.Runtime.InteropServices.Marshal.AllocHGlobal(16);

// Hacer algo con la memoria asignada

// Liberar la memoria asignada


System.Runtime.InteropServices.Marshal.FreeHGlobal(pointer);

El .NET Framework incluye muchas clases y m�todos en el sistema y los espacios de


nombres System.Runtime.InteropServices (como la clase Marshal) que convierten tipos
de.NET (por ejemplo, System.String) desde y hacia muchos tipos no administrados y
punteros (por ejemplo, LPWSTR o void *) para permitir la comunicaci�n con c�digo no
administrado.
COBOL

El lenguaje de programaci�n COBOL soporta punteros a variables. Los objetos


primitivos o datos de grupos (graban) objetos de datos declarados dentro de la
LINKAGE SECTION de un programa son inherentemente basados en punteros, donde la
�nica memoria asignada en el programa es el espacio para la direcci�n del elemento
de datos (normalmente una palabra de memoria individual), basados en punteros. En
el c�digo fuente del programa, estos elementos de datos son utilizados como
cualquier otra variable WORKING-STORAGE, pero sus contenidos est�n indirecta e
impl�citamente accedidos a trav�s de sus punteros LINKAGE.

El espacio de memoria para cada se�al� a objeto de datos se suelen asignar


din�micamente utilizando las sentencias CALL externos o a trav�s de construcciones
del lenguaje extendidos embebidas como EXEC CICS o sentencias EXEC SQL

Las versiones extendidas de COBOL tambi�n proporcionan variables de puntero


declarados con cl�usulas USAGE IS POINTER. Los valores de estas variables de
puntero se establecen y modifican usando SET y declaraciones SET ADDRESS.

Algunas versiones extendidas de COBOL tambi�n proporcionan variables de PROCEDURE-


POINTER triple, que son capaces de almacenar las direcciones de c�digo ejecutable.
PL/I

El lenguaje PL/I proporciona soporte completo para punteros a todos los tipos de
datos (incluyendo punteros a estructuras), recursividad, multitarea, manejo de
cadenas, y amplias funciones incorporadas. PL/I era un salto absoluto hacia
adelante en comparaci�n con los lenguajes de programaci�n de su tiempo.[cita
requerida]
D

El lenguaje de programaci�n D es un derivado de C y C++, que es totalmente


compatible con los punteros de C y los typecasting de C.
Eiffel

El lenguaje Eiffel orientado a objetos soporta punteros en forma de referencias,


que se escriben y no permiten ning�n tipo de aritm�tica de punteros. El est�ndar
ECMA para Eiffel incluye un mecanismo de "tipo adjunto" que pretende garantizar un
void seguro.
Fortran

Fortran-90 introdujo la capacidad de puntero inflexible de tipos. Los punteros en


Fortran contienen algo m�s que una simple direcci�n de memoria. Tambi�n encapsulan
los l�mites inferior y superior de dimensiones de matriz, pasos (por ejemplo, para
soportar a las secciones de matriz arbitrarias), y otros metadatos. Un operador
asociaci�n, => se utiliza para asociar un puntero a una variable que tiene un
atributo TARGET. El Fortran-90 tambi�n se puede usar la declaraci�n ALLOCATE para
asociar un puntero a un bloque de memoria. Por ejemplo, el siguiente c�digo podr�a
ser usado para definir y crear una estructura de lista enlazada:

type real_list_t
real :: sample_data(100)
type (real_list_t), pointer :: next => null ()
end type

type (real_list_t), target :: my_real_list


type (real_list_t), pointer :: real_list_temp
real_list_temp => my_real_list
do
read (1,iostat=ioerr) real_list_temp%sample_data
if (ioerr /= 0) exit
allocate (real_list_temp%next)
real_list_temp => real_list_temp%next
end do

Fortran-2003 a�ade soporte para punteros de procedimiento. Tambi�n, como parte de


la funci�n de Interoperabilidad de C, Fortran-2003 es compatible con las funciones
intr�nsecas para la conversi�n de punteros al estilo C a punteros Fortran y
traseros.
Go

Go tiene punteros. Su sintaxis de declaraci�n es equivalente a la de C, pero


escrito al rev�s, terminando con el tipo. A diferencia de C, Go tiene la
recolecci�n de basura, y no permite la aritm�tica de punteros. Al igual que en C++,
no existen los tipos de referencia. Algunos tipos incorporados, como los mapas y
canales, est�n encuadradas (es decir, internamente son punteros a estructuras
mutables), y se inicializan utilizando la funci�n make. Como un enfoque diferente
(que los tipos de referencia) a la sintaxis unificada entre punteros y no punteros,
el operador flecha (->) se ha dejado caer�es posible utilizar el operador punto
directamente en un puntero a un tipo de datos para acceder a un �mbito o m�todo del
valor desreferenciado, como si el operador punto se utiliza en el tipo de datos
subyacente. Esto, sin embargo, solo funciona con 1 nivel de indirecci�n.
Java

A diferencia de C, C++ o Pascal, no hay representaci�n expl�cita de punteros en


Java. En cambio, las estructuras de datos m�s complejas como los objetos y las
matrices se implementan utilizando referencias. El lenguaje no ofrece operadores
expl�citos de manipulaci�n de punteros. A�n es posible para el c�digo intentar
eliminar la referencia de una referencia nula (puntero null), sin embargo, lo que
resulta en una excepci�n de tiempo de ejecuci�n que es lanzada. El espacio ocupado
por objetos de memoria no referenciados se recupera autom�ticamente recolectando la
basura en tiempo de ejecuci�n.20?
Modula-2

Los punteros son fuertemente implementados como en Pascal, al igual que los
par�metros VAR en las llamadas a procedimiento. Modula-2 es m�s inflexible incluso
que Pascal, con al menos v�as de escape del sistema de tipos. Algunas de las
variantes de Modula-2 (como Modula-3) incluyen recolecci�n de basura.
Oberon

Al igual que Modula-2, los punteros est�n disponibles. A�n hay un menor n�mero de
maneras de evadir el sistema de tipos y as� Oberon y sus variantes son a�n m�s
seguros con respecto a los punteros de Modula-2 o sus variantes. Al igual que con
Modula-3, la recolecci�n de basura es una parte de la especificaci�n del lenguaje.
Pascal

A diferencia de muchas lenguajes que cuentan con punteros, el est�ndar ISO Pascal
solo permite punteros para hacer referencia a las variables creadas din�micamente
que son an�nimas y no les permiten referenciar est�ndares est�ticos o variables
locales.21? No tiene aritm�tica de punteros. Los punteros deben tambi�n de tener un
tipo asociado, y un puntero a un tipo no es compatible con un puntero a otro tipo
(por ejemplo, un puntero a un char no es compatible con un puntero a un entero).
Esto ayuda a eliminar los problemas de seguridad inherentes tipo con otras
implementaciones de puntero, especialmente los utilizados para PL/I o C. Tambi�n
elimina algunos riesgos causados por punteros colgados, pero la capacidad de dejar
de lado el espacio de forma din�mica se hace referencia mediante el procedimiento
est�ndar dispose (que tiene el mismo efecto que la funci�n de la liber�a free
encontrada en C) significa que el riesgo de punteros no se ha eliminado por
completo.22?

Sin embargo, en algunas implementaciones comerciales y de c�digo abierto de


compiladores de Pascal (o derivados)-como Free Pascal,23? Turbo Pascal o Object
Pascal en Embarcadero Delphi�se le permite un puntero hacer referencia a las
variables est�ticas o locales est�ndares y se puede lanzar desde un tipo puntero a
otro. Por otra parte la aritm�tica de punteros est� restringida: a�adiendo o
restando de un puntero se mueve por ese n�mero de bytes en cualquier direcci�n,
pero utilizando los procedimientos est�ndar Inc o Dec con que se mueve el puntero
por el tama�o del tipo de datos que se declara a apuntar. Un puntero sin tipo
tambi�n proporciona bajo el nombre de Pointer, que es compatible con otros tipos de
puntero.
Pauscal

El lenguaje de programaci�n Pauscal presenta un fuerte soporte de punteros,


permitiendo apuntar a variables, estructuras, procedimientos, prototipos, uniones e
incluso clases y sus m�todos. Los punteros se pueden utilizar para almacenar la
direcci�n en memoria de un objeto o para crear una referencia a este. Pauscal
utiliza los punteros para convertir tipos de datos sin necesidad de ninguna
interfaz de programaci�n de aplicaciones (API) externa, aumentando la velocidad de
ejecuci�n de los programas ligeramente y permitiendo que estos sean "nativos" del
lenguaje.
Perl
El lenguaje de programaci�n Perl soporta punteros, aunque raramente se utilizan, en
forma de funciones de empaquetado y desempaquetado. Estos est�n destinados
�nicamente a las interacciones simples con bibliotecas OS compiladas. En todos los
dem�s casos, Perl utiliza referencias, que se escriben y no permiten ning�n tipo de
aritm�tica de punteros. Estos se utilizan para construir complejas estructuras de
datos.24?

Vous aimerez peut-être aussi