fbpx
Wikipedia

Puntero (informática)

Considero que las sentencias de asignación y variables puntero están entre los tesoros más valiosos de la informática 100
Donald Knuth, Structured Programming with go to Statements[1]

En ciencias de la computación, un puntero es un objeto del lenguaje de programación, cuyo valor se refiere a (o "apunta a") otro valor almacenado en otra parte de la memoria del ordenador utilizando su dirección. Un puntero referencia a una ubicación en memoria, y a la obtención del valor almacenado en esa ubicación se la conoce como desreferenciación del puntero. A modo de analogía, un número de página en el índice de un libro podría considerarse un puntero a la página correspondiente; desreferenciar un puntero sería como ir a la página con el número de página especificada en el índice.

Puntero 'a' apuntando a la dirección de memoria asociada con la variable 'b'. Obsérvese que en este diagrama en particular, la arquitectura de cálculo utiliza el mismo espacio de direcciones y datos primitivos tanto para punteros como para no punteros; esto no tiene por qué ser el caso.

Los punteros a datos mejoran significativamente el rendimiento de las operaciones repetitivas tales como cadenas de desplazamiento, tablas de búsqueda, tablas de control y estructuras árbol. En particular, muchas veces es mucho más barato en tiempo y espacio copiar y des referenciar punteros que copiar y acceder a los datos a los cuales apunta el puntero.

Los punteros también se utilizan para mantener las direcciones de los puntos de entrada para las subrutinas para llamadas en programación por procedimientos y enlaces para vincular a las bibliotecas de enlace dinámico (DLL) en tiempo de ejecución. En la programación orientada a objetos, los punteros a funciones se utilizan para métodos de unión, muchas veces utilizando lo que se llama tablas de métodos virtuales.

Un puntero es una implementación más concreta y simple del tipo de datos de referencia más abstracto. Varios lenguajes soportan algún tipo de puntero, aunque algunos tengan más restricciones en su uso que otros. Mientras que se utilice un "puntero" para referirse a referencias en general, se aplica más propiamente a las estructuras de datos cuya interfaz permita explícitamente que el puntero sea manipulado (aritméticamente vía aritmética de punteros) como una dirección de memoria, en oposición a una cookie u opción dónde esto no sea posible.[cita requerida] Debido a que los punteros permiten tanto proteger como permitir el acceso a direcciones de memoria, hay riesgos asociados con su uso, sobre todo en este último caso. Generalmente, los punteros primitivos son almacenados en un formato similar a un entero; no obstante, intentar eliminar la referencia o "mirar hacia arriba" hacia un puntero cuyo valor no fue nunca una dirección de memoria válida conllevaría a provocar que un programa se bloquee. Para aliviar este potencial problema, como una cuestión de seguridad de tipos, los punteros son considerados un tipo separado parametrizado por un tipo de datos que apuntan a, incluso si la representación subyacente es un número entero. También se pueden tomar otras medidas (como la validación y comprobación de los límites, para verificar el contenido de la variable de puntero contenga un valor que es a la vez una dirección de memoria válida y dentro del rango numérico que el procesador sea capaz de abordar).

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 por 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

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 datos[10]​ 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 porqué 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 nulo[15]​ 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,  , tiene un elemento puntero auto relativo,  , que apunta a una porción   de sí mismo, entonces   puede ser reubicado en la memoria sin tener que actualizar el valor de  .[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 ítem.

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 devuelve 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 librerí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]

Véase también

Referencias

  1. Donald Knuth (1974). (pdf). Computing Surveys (en inglés) 6 (5): 261-301. doi:10.1145/356635.356640. Archivado desde el original el 19 de mayo de 2013. 
  2. Milestones in Computer Science and Information Technology
  3. . Archivado desde el original el 22 de marzo de 2011. Consultado el 16 de abril de 2015. 
  4. ISO/IEC 9899, cláusua 6.7.5.1, párrafo 1.
  5. ISO/IEC 9899, cláusula 6.7.8, párrafo 10.
  6. ISO/IEC 9899, cláusula 7.17, párrafo 3: NULL... que expande a una implementación definida como puntero constante nulo...
  7. ISO/IEC 9899, cláusula 6.5.3.2, párrafo 4, footnote 87: Si un valor no válido ha sido asignada al puntero, el comportamiento del operador unario * es indefinido... Entre los valores válidos para desreferenciar un puntero por el operador unario * son un puntero nulo...
  8. Plauger, P J; Brodie, Jim (1992). ANSI and ISO Standard C Programmer's Reference. Redmond, WA: Microsoft Press. pp. 108, 51. ISBN 1-55615-359-7. «Un tipo de matriz no contiene agujeros adicionales porque todos los otros tipos de paquetes se hermetizan cuando están compuestos en matrices [en página 51]». 
  9. WG14 N1124, C – Approved standards: ISO/IEC 9899 – Programming languages – C, 6 de mayo de 2005.
  10. ISO/IEC 9899, cláusula 6.3.2.3, párrafo 4.
  11. ISO/IEC 9899, cláusula 6.3.2.3, párrafo 3.
  12. Stroustrup, Bjarne (marzo de 2001). «Chapter 5: Pointers, Arrays, and Structures: 5.1.1: Zero». The C++ Programming Language (14ta impresión de la 3ra edición). Estados Unidos y Canadá: Addison–Wesley. p. 88. ISBN 0-201-88954-4. «En C, ha sido popular definir un macro NULL para representar el puntero cero. Debido a que en C++ es más estricta la comprobación de tipo, el uso del 0 plano, en lugar de cualquier macro NULL sugerido, conduce a un menor número de problemas. Si se necesita definir NULL. utilizar : const int NULL = 0; El calificador const (§ 5.4) previene redefinición accidental de NULL y se asegura de que NULL se puede utilizar cuando se requiere una constante.» 
  13. Tony Hoare (2009). . QCon London. Archivado desde el original el 19 de enero de 2009. Consultado el 15 de marzo de 2014. 
  14. Tony Hoare (25 de agosto de 2009). «Null References: The Billion Dollar Mistake». InfoQ.com. 
  15. ISO/IEC 9899, cláusula 6.5.3.2, párrafo 4.
  16. The Objective-C 2.0 Programming Language, sección "Sending Messages to nil".
  17. Plantilla:Cita patente
  18. Plantilla:Cita patente
  19. Based Pointers
  20. Nick Parlante, [1], Stanford Computer Science Education Library, pp. 9–10 (2000). (en inglés)
  21. ISO 7185 Pascal Standard (unofficial copy), section 6.4.4 Pointer-types y subsecuentes.
  22. J. Welsh, W. J. Sneeringer, and C. A. R. Hoare, "Ambiguities and Insecurities in Pascal," Software Practice and Experience 7, pp. 685–696 (1977)
  23. Free Pascal Language Reference guide, section 3.4 Pointers
  24. // Making References (Perl References and nested data structures) (en inglés)

Enlaces externos

  • Punteros en C/C++ y correspondencia entre arrays y punteros.
  • Memoria dinámica en C: malloc, realloc y free.
  • Punteros y Memoria Introducción a los punteros - Biblioteca de Educación de las Ciencias de la Computación de Stanford
  • 0pointer.de Una lista concisa de los códigos de longitud mínima que referencian a un puntero nulo en diversos lenguajes de programación diferentes.
  • Memoria dinámica en C++: Operadores new y delete.
  • "The C book" – containing pointer examples in ANSI C
  • Joint Technical Committee ISO/IEC JTC 1, Subcommittee SC 22, Working Group WG 14 (8 de setiembre de 2007). International Standard ISO/IEC 9899 (PDF) (en inglés). Committee Draft. 
  •   Datos: Q118155
  •   Multimedia: Pointers (computing)

puntero, informática, considero, sentencias, asignación, variables, puntero, están, entre, tesoros, más, valiosos, informática, donald, knuth, structured, programming, with, statements, ciencias, computación, puntero, objeto, lenguaje, programación, cuyo, valo. Considero que las sentencias de asignacion y variables puntero estan entre los tesoros mas valiosos de la informatica 100 Donald Knuth Structured Programming with go to Statements 1 En ciencias de la computacion un puntero es un objeto del lenguaje de programacion cuyo valor se refiere a o apunta a otro valor almacenado en otra parte de la memoria del ordenador utilizando su direccion Un puntero referencia a una ubicacion en memoria y a la obtencion del valor almacenado en esa ubicacion se la conoce como desreferenciacion del puntero A modo de analogia un numero de pagina en el indice de un libro podria considerarse un puntero a la pagina correspondiente desreferenciar un puntero seria como ir a la pagina con el numero de pagina especificada en el indice Puntero a apuntando a la direccion de memoria asociada con la variable b Observese que en este diagrama en particular la arquitectura de calculo utiliza el mismo espacio de direcciones y datos primitivos tanto para punteros como para no punteros esto no tiene por que ser el caso Los punteros a datos mejoran significativamente el rendimiento de las operaciones repetitivas tales como cadenas de desplazamiento tablas de busqueda tablas de control y estructuras arbol En particular muchas veces es mucho mas barato en tiempo y espacio copiar y des referenciar punteros que copiar y acceder a los datos a los cuales apunta el puntero Los punteros tambien se utilizan para mantener las direcciones de los puntos de entrada para las subrutinas para llamadas en programacion por procedimientos y enlaces para vincular a las bibliotecas de enlace dinamico DLL en tiempo de ejecucion En la programacion orientada a objetos los punteros a funciones se utilizan para metodos de union muchas veces utilizando lo que se llama tablas de metodos virtuales Un puntero es una implementacion mas concreta y simple del tipo de datos de referencia mas abstracto Varios lenguajes soportan algun tipo de puntero aunque algunos tengan mas restricciones en su uso que otros Mientras que se utilice un puntero para referirse a referencias en general se aplica mas propiamente a las estructuras de datos cuya interfaz permita explicitamente que el puntero sea manipulado aritmeticamente via aritmetica de punteros como una direccion de memoria en oposicion a una cookie u opcion donde esto no sea posible cita requerida Debido a que los punteros permiten tanto proteger como permitir el acceso a direcciones de memoria hay riesgos asociados con su uso sobre todo en este ultimo caso Generalmente los punteros primitivos son almacenados en un formato similar a un entero no obstante intentar eliminar la referencia o mirar hacia arriba hacia un puntero cuyo valor no fue nunca una direccion de memoria valida conllevaria a provocar que un programa se bloquee Para aliviar este potencial problema como una cuestion de seguridad de tipos los punteros son considerados un tipo separado parametrizado por un tipo de datos que apuntan a incluso si la representacion subyacente es un numero entero Tambien se pueden tomar otras medidas como la validacion y comprobacion de los limites para verificar el contenido de la variable de puntero contenga un valor que es a la vez una direccion de memoria valida y dentro del rango numerico que el procesador sea capaz de abordar Indice 1 Historia 2 Descripcion formal 3 Usos en estructuras de datos 4 Uso en tablas de control 5 Origenes en la arquitectura de ordenador 6 Usos 6 1 Punteros en C 6 2 Matrices de C 7 Lista vinculada en C 7 1 Pasaje por direccion utilizando punteros 7 2 Asignacion dinamica de memoria 7 3 Hardware asignado en memoria 8 Punteros con tipo y fundicion 9 Haciendo mas seguros a los punteros 10 Puntero nulo 11 Puntero auto relativo 12 Puntero base 13 Indireccion multiple 14 Puntero a funcion 15 Puntero salvaje 16 Simulacion utilizando un indice de matriz 17 Punteros en lenguajes de programacion 17 1 Estructuras 17 2 Uniones 17 3 Matrices 18 Soporte en lenguajes de programacion 18 1 Ada 18 2 BASIC 18 3 C y C 18 4 C 18 5 COBOL 18 6 PL I 18 7 D 18 8 Eiffel 18 9 Fortran 18 10 Go 18 11 Java 18 12 Modula 2 18 13 Oberon 18 14 Pascal 18 15 Pauscal 18 16 Perl 19 Vease tambien 20 Referencias 21 Enlaces externosHistoria EditarSe le atribuye a Harold Lawson la invencion del puntero en 1964 2 En 2000 Lawson fue presentado el Premio Pionero de Informatica por la IEEE por la invencion de la variable puntero y la introduccion de este concepto en PL I proporcionando asi por primera vez la capacidad de tratar con flexibilidad las listas enlazadas en un lenguaje de alto nivel de proposito general 3 Segun el Diccionario ingles de Oxford la palabra puntero aparecio impresa por primera vez como un puntero de pila en un memorando tecnico de la System Development Corporation Corporacion de Desarrollo de Sistemas Descripcion formal EditarEn ciencias de la computacion un puntero es un tipo de referencia Un dato primitivo o simplemente primitivo es cualquier dato que puede ser leido 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 logicamente contiguos en la memoria y que son vistos colectivamente como un dato por ejemplo un agregado podria ser 3 bytes logicamente contiguos los valores de los cuales representan las 3 coordenadas de un punto en el espacio Cuando un agregado esta 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 esta destinado a ser utilizado como una direccion de memoria se dice que un puntero apunta a una direccion de memoria Tambien se dice que un puntero apunta a un dato en memoria cuando el valor del puntero es la direccion de memoria de referencia Mas en general un puntero es un tipo de referencia y se dice que un puntero referencia a un dato almacenado en algun lugar de la memoria para obtener ese dato se desreferencia el puntero La caracteristica que separa punteros de otros tipos de referencia es que el valor de un puntero esta destinado a ser interpretado como una direccion de memoria que es un concepto bastante de bajo nivel Las referencias sirven como un nivel de indireccion El valor de un puntero determina que la direccion de memoria es decir cual dato esta siendo utilizado en un calculo Debido a que la indireccion es un aspecto fundamental de los algoritmos generalmente los punteros son expresados como un tipo de datos fundamental en lenguajes de programacion en forma de lenguajes de programacion estaticos o fuertemente tipados el tipo de un puntero determina el tipo de dato al que apunta el puntero Usos en estructuras de datos EditarCuando se configuren estructuras de datos como listas colas y arboles es necesario contar con indicadores para ayudar a controlar como se implementa y controla la estructura Ejemplos tipicos de punteros son los de inicio los punteros finales y los punteros de pila Estos indicadores pueden ser o bien absolutos direccion fisica real o una direccion virtual en la memoria virtual o relativos un desplazamiento desde una direccion inicial absoluta base que suele utilizar menos bits que una direccion completa pero por lo general requieren una operacion aritmetica adicional para resolverse Las direcciones relativas son una forma de segmentacion de memoria manual y comparten muchas de sus ventajas y desventajas Una compensacion 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 facilmente a 128K 256K o 512K si la direccion apuntada se ve obligada a alinearse a mitad de palabras palabra o doble palabra pero lo que requiere una operacion de desviacion 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 adicion a la direccion de base Sin embargo por lo general esos planos tienen un monton de problemas y por conveniencia para el programador son preferibles las direcciones absolutas del programador y subyacente a esa un espacio de direccion plano A un byte offset tal como el valor ASCII hexadecimal de un caracter por ejemplo X 29 se puede utilizar para apuntar a un valor alternativo entero o indice 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 indice secuencial utilizable y luego a una direccion absoluta sin utilizar una tabla de busqueda Uso en tablas de control EditarPor 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 indices 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 programacion Tambien pueden utilizarse para senalar 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 ultimo efecto el puntero simplemente puede ser el numero de entrada de la tabla en si y puede pasar a ser una direccion actual usando aritmetica simple Origenes en la arquitectura de ordenador EditarLos punteros son una abstraccion muy delgada en la parte superior de las capacidades de direccionamiento ofrecidas por la mayoria de las arquitecturas modernas En el esquema mas simple una direccion o un indice numerico se asigna a cada unidad de memoria en el sistema donde la unidad es tipicamente 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 direccion el sistema provee una operacion para recuperar el valor almacenado en la unidad de memoria en esa direccion por lo general la utilizacion de registros de proposito general de la maquina En el caso usual un puntero es lo suficientemente grande como para contener mas direcciones que no sean unidades de memoria en el sistema Esto introduce la posibilidad de que un programa puede intentar acceder a una direccion que corresponde a ninguna unidad de memoria ya sea porque no hay suficiente memoria instalada es decir mas alla 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 segmentacion violacion de segmento El segundo caso es posible en la actual aplicacion de AMD64 donde los punteros son de 64 bits de largo y direcciones solo se extienden a 48 bits Alli punteros deben ajustarse a ciertas normas canonicas direcciones asi que si un puntero no canonica se eliminan las referencias el procesador plantea un error de proteccion general Por otra parte algunos sistemas tienen mas unidades de memoria que no son direcciones En este caso se emplea un esquema mas complejo tal como la segmentacion de memoria o de paginacion a utilizar diferentes partes de la memoria en diferentes momentos Las ultimas encarnaciones de la arquitectura x86 soportan hasta 36 bits de direcciones de memoria fisica que fueron asignadas al espacio de direcciones lineal de 32 bits usando un mecanismo PAE de paginacion Asi 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 fisica pudiendo acceso a un maximo de 1 GiB de memoria virtual pero la combinacion de direccion de 16 bits y el segmento de registros hizo acceder a mas de 64 KiB en una estructura de datos engorroso Algunas restricciones de la aritmetica 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 analogos tales como desplazamientos de archivo los indices de matriz y las referencias a objetos remotos que sirven algunos de los mismos propositos que las direcciones de otros tipos de objetos Usos EditarLos punteros son compatibles directamente sin restricciones en lenguajes como PL 1 C C Pascal y la mayoria de los lenguajes ensambladores Se utilizan principalmente para la construccion de referencias que a su vez son fundamentales para la construccion de casi todas las estructuras de datos asi como para pasar datos entre las diversas partes de un programa En los lenguajes de programacion 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 critica operacion de busqueda suele implicar un calculo de direccion etapa llamada que implica la construccion 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 aritmetica es por lo general un poco mas 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 explicita una sola pieza de la estructura a otra Los punteros se utilizan para pasar parametros por referencia Esto es util si el programador quiere modificaciones de una funcion a un parametro sea visible para llamador de la funcion de la funcion Esto tambien es util para devolver varios valores de una funcion Los punteros tambien se puede utilizar para asignar y desasignar en la memoria variables dinamicas y matrices Ya que muchas veces una variable puede volverse redundante despues de que haya cumplido su objetivo que resulta en una perdida de la memoria mantenerla en consecuencia es una buena practica para desasignarla cuando ya no se necesita utilizando la referencia de puntero original El no hacerlo puede resultar en una perdida de memoria donde la memoria libre disponible va disminuyendo gradualmente o en casos severos rapidamente a causa de una acumulacion de numerosos bloques de memoria redundantes Punteros en C Editar La sintaxis basica 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 intEsto usualmente se manifiesta de forma mas sucinta como ptr es un puntero a int Debido a que el lenguaje C no especifica una inicializacion implicita para los objetos de duracion automatica de almacenamiento 5 frecuentemente se debe prestar atencion para asegurarse de que la direccion a la que ptr puntea es valida por eso a veces se sugiere que un puntero pueda ser explicitamente 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 podria ser catastrofico Sin embargo la mayoria de las implementaciones cita requerida simplemente detienen la ejecucion del programa en cuestion usualmente con un fallo de segmentacion Sin embargo punteros inicializados podria obstaculizar innecesariamente el analisis del programa ocultando de ese modo los bugs En cualquier caso una vez que un puntero ha sido declarado el siguiente paso logico es que se apunte a algo int a 5 int ptr NULL ptr amp a Esto asigna el valor de la direccion de a a ptr Por ejemplo si a esta almacenado en la ubicacion de memoria de 0x8130 entonces el valor de ptr sera 0x8130 despues de la asignacion 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 direccion en memoria y establecer su valor en 8 Si mas tarde se accede de nuevo su nuevo valor sera 8 Este ejemplo puede ser mas claro si la memoria no es directamente examinada Supongamos que a se localiza en la direccion 0x8130 en memoria y ptr en 0x8134 tambien 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 estaria en la memoria despues de que se ejecuta el siguiente fragmento de codigo int a 5 int ptr NULL Direccion Contenido0x8130 0x000000050x8134 0x00000000 El puntero NULL que se muestra aqui es 0x00000000 Mediante la asignacion la direcciona de a a ptr ptr amp a produce los siguientes valores de memoria Direccion Contenido0x8130 0x000000050x8134 0x00008130Entonces desreferenciando ptr mediante codificacion ptr 8 la computadora tendra el contenido de ptr que es 0x8130 localizado esa direccion y asignar 8 a esa ubicacion produciendo la siguiente memoria Direccion Contenido0x8130 0x000000080x8134 0x00008130Claramente el acceso a a producira el valor de 8 porque la instruccion anterior modifico el contenido de a por medio del puntero ptr Matrices de C Editar En C la indizacion de matrices se define formalmente en terminos de punteros aritmeticos es decir la especificacion del lenguaje requiere que array i sea equivalente a array i 8 Asi en C las matrices pueden ser consideradas como punteros a areas de memoria consecutivas sin espacios vacios 8 y la sintaxis para acceder a las matrices es identica 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 adicion del puntero es conmutativa 2 array 4 El operador subindice es conmutativo Esto asigna un bloque de cinco enteros y nombres de la matriz por bloques que actua como un puntero al bloque Otro uso comun de los punteros es para que apunte a la memoria asignada dinamicamente desde malloc que devuelve un bloque consecutivo de memoria de no menos que el tamano solicitado que se puede utilizar como una matriz Aunque la mayoria de los operadores sobre matrices y punteros sean equivalentes es importante tener en cuenta que el operador sizeof sera diferente En este ejemplo sizeof array evaluara a 5 sizeof int el tamano de la matriz mientras que sizeof ptr evaluara sizeof int el tamano 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 direccion 0x1000 de una maquina little endian de 32 bits entonces la memoria contendra lo siguiente los valores se encuentran en hexadecimal asi como las direcciones 0 1 2 31000 2 0 0 01004 4 0 0 01008 3 0 0 0100C 1 0 0 01010 5 0 0 0Aqui estan 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 direccion 0x1000 La sintaxis de C con punteros es array significa 0x1000 array 1 significa 0x1004 tener en cuenta que en realidad significa el 1 anade una vez el tamano de un int 4 bytes no literalmente mas uno array significa desreferenciar los contenidos de array Teniendo en cuenta el contenido como una direccion de memoria 0x1000 buscar el valor en esa ubicacion 0x0002 array i significa numero de elemento i base 0 de la matriz que se traduce en array i El ultimo ejemplo es como acceder a los contenidos del array Descomponiendolo array i es la posicion de memoria de la i 1 esimo elemento de la matriz array i toma esa direccion de memoria y elimina referencias a acceder al valor Por ejemplo array 3 es sinonimo 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 EditarA continuacion se muestra un ejemplo de definicion de una lista enlazada en C la lista enlazada vacia esta representada por NULL o algun otro valor centinela define EMPTY LIST NULL struct link void datos datos de este vinculo struct link proximo siguiente enlace EMPTY LIST si no hay ninguno Notese que esta definicion puntero recursivo es esencialmente la misma que la definicion de referencia recursiva del lenguaje de programacion Haskell data Link a Nil Cons a Link a Nil es la lista vacia y Cons a Link a es una cons cell de un tipo a con otro enlace tambien de tipo a Sin embargo la definicion de referencias es de tipo comprobado y no utiliza los valores de senal potencialmente confusos Por esta razon en C las estructuras de datos normalmente se tratan a traves de funciones contenedor que son cuidadosamente verificadas para su correccion Pasaje por direccion utilizando punteros Editar Los punteros se pueden usar para pasar variables por su direccion lo que permite cambiar su valor A modo de ejemplo se considera el siguiente codigo en C include lt stdio h gt se puede cambiar una copia de int n dentro de la funcion sin afectar el codigo de llamada void passbyvalue int n n 12 En su lugar se pasa un puntero a m No se crea ninguna copia m de si 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 funcion pero x sigue siendo 3 de aqui posteriormente pasar la direccion de x como argumento passbyaddress amp x en realidad x fue cambiada por la funcion y ahora aqui es igual a 14 return 0 Asignacion dinamica de memoria Editar Los punteros se utilizan para almacenar y administrar las direcciones de los bloques de memoria asignados dinamicamente Dichos bloques se utilizan para almacenar objetos o conjuntos de objetos de datos Los lenguajes mas estructurados y orientados a objetos proporcionan un area de memoria llamada el monton o tienda libre de la que objetos dinamicamente asignados El codigo de ejemplo C siguiente ilustra como se asignan dinamicamente objetos de estructura y referencia La biblioteca C estandar proporciona la funcion malloc para asignar bloques de memoria desde el monton Se necesita el tamano de un objeto para asignarlo como parametro y devolver un puntero a un bloque recien asignado de memoria adecuado para almacenar el objeto o se devuelve un puntero nulo si la asignacion falla Item de inventario de partes struct Item int id Numero 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 gt id 1 Item gt name NULL Item gt cost 0 0 Guarde una copia del nombre en el nuevo elemento Item gt name char malloc strlen name 1 if Item gt name NULL free Item return NULL strcpy Item gt name name Devuelve el objeto de articulos recientemente creados return Item El codigo siguiente muestra como se desasignan dinamicamente objetos de memoria es decir retorna al monton o tienda libre La biblioteca C estandar proporciona la funcion free para cancelar la asignacion de un bloque de memoria previamente asignado y retornar de nuevo al monton 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 gt name NULL free item gt name item gt name NULL Desasignar el propio objeto Item free item Hardware asignado en memoria Editar En algunas arquitecturas de computacion los punteros pueden ser utilizados para manipular directamente de memoria o dispositivos asignados a la memoria La asignacion direcciones a los punteros es una herramienta invaluable en la programacion de microcontroladores A continuacion se muestra un simple ejemplo de declaracion de un puntero de tipo int y la inicializacion a una direccion hexadecimal en este ejemplo el constante 0x7FFF int hardware address int 0x7FFF A mediados de los anos 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 video 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 consistia en un codigo ASCII en el byte bajo y un color en el byte alto Por lo tanto para poner la letra A en la linea 5 columna 2 blanco sobre azul luminoso uno podria escribir codigo como el siguiente define VID unsigned short 80 0xB8000 void foo VID 4 1 0x1F00 A Punteros con tipo y fundicion EditarEn muchos lenguajes los punteros tienen la restriccion adicional de que el objeto que apuntan tiene un tipo especifico Por ejemplo un indicador puede ser declarado para apuntar a un numero entero sera el lenguaje el que trate de evitar que el programador apunte a objetos que no fuesen numeros enteros tales como numeros de coma flotante eliminando algunas errores Por ejemplo en C int money char bags money seria un puntero entero y bags seria un puntero char Lo siguiente daria una advertencia del compilador de asignacion 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 explicita de que realmente se desea hacer la cesion 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 estandar de 2005 requiere que echando un puntero derivado de un tipo a uno de otro tipo debia mantener la correccion de alineacion 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 esta correctamente alineado En lenguajes que permiten la aritmetica de punteros dicha aritmetica en punteros tiene en cuenta el tamano del tipo Por ejemplo la adicion de un numero entero a un puntero produce otro puntero que apunta a una direccion que es superior en numero de veces que el tamano del tipo Esto nos permite calcular facilmente la direccion de elementos de una matriz de un tipo determinado como se demostro en el ejemplo matrices C descripto arriba Cuando un puntero de un tipo se convierte en otro tipo de un tamano diferente el programador debe esperar que el puntero aritmetico 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 apuntara a 0x2004 pero bags 1 apuntara a 0x2001 Entre otros riesgos de la fundicion se incluyen la perdida 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 comparacion sobre todo entre valores con signo vs valores sin signo Aunque por lo general sea imposible determinar en tiempo de compilacion que arroja son seguros algunos lenguajes almacenan el tipo de informacion en tiempo de ejecucion que puede ser utilizado para confirmar que estos peligrosos moldes son validos en tiempo de ejecucion Otros lenguajes simplemente aceptan una aproximacion conservadora de moldes seguros o ninguno en absoluto Haciendo mas seguros a los punteros Editar El texto que sigue es una traduccion defectuosa Si quieres colaborar con Wikipedia busca el articulo original y mejora esta traduccion Copia y pega el siguiente codigo en la pagina de discusion del autor de este articulo subst Aviso mal traducido Puntero informatica 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 programacion Sin embargo la utilidad de los punteros es tan grande que puede ser dificil realizar tareas de programacion sin ellos En consecuencia muchos lenguajes han creado construcciones disenadas para proporcionar algunas de las caracteristicas utiles de los punteros sin algunas de sus trampas tambien denominadas algunas veces peligros de punteros En este contexto los punteros que se dirigen directamente a la memoria como se usa en este articulo 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 numero se pueden hacer que este apunte a direcciones no utilizadas o a datos que se esta utilizando para otros fines Muchos lenguajes incluyendo lenguajes de programacion funcionales y los ultimos lenguajes imperativos como Java reemplazan los punteros con un tipo mas opaco de referencia tipicamente referido simplemente como referencia que solo puede ser usado para referirse a los objetos y no manipula a los numeros previniendo este tipo de error La indexacion de una matriz se trata como un caso especial Un puntero que no tenga ninguna direccion 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 direccion valida o porque su uso puede danar otras partes del programa El resultado suele ser un fallo de segmentacion violacion de almacenamiento o rama natural si se utiliza como un puntero de funcion o de direccion de rama En sistemas con asignacion de memoria explicita es posible crear un puntero de referencia colgante para des asignar la direccion de memoria que apunta dentro Este tipo de puntero es peligroso y sutil ya una region de memoria des asignada puede contener los mismos datos como lo hizo antes de que se cancele la asignacion pero puede ser reasignado a continuacion y se sobrescriben con codigo ajeno desconocido para el codigo anterior Los lenguajes con recolector de basura previenen este tipo de error porque des afectacion se realiza automaticamente cuando no hay mas 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 asignacion de un registro de la memoria dinamica ademas de actuar como referencia En la ausencia de ciclos de referencia donde un objeto se auto refiere indirectamente mediante una secuencia de punteros inteligentes estos eliminan la posibilidad de punteros colgantes y perdidas de memoria Las cadenas en Delphi soportan de forma nativa recuento de referencias Puntero nulo EditarUn puntero nulo tiene un valor reservado para indicar que el puntero no se refiere a un objeto valido 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 algun tipo de accion 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 opcion Frecuentemente los punteros nulos se consideran similares a los valores nulos en las bases de datos relacionales pero tienen una semantica algo diferente En la mayoria de los lenguajes de programacion un puntero nulo significa ningun valor mientras que en una base de datos relacional un valor nulo significa valor desconocido Esto conduce a importantes diferencias en la practica en la mayoria de los lenguajes de programacion 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 programacion al menos por ejemplo una implementacion 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 aplicacion pero no accesible explicitamente desde los programas de usuario permitiendo asi que el mismo registro sea utilizado como una constante util y una forma rapida de acceder a partes internas de aplicacion Esto se conoce como vector i nil i nulo En C dos punteros nulos de cualquier tipo estan garantidos para comparar iguales tipo de datos 10 El macro NULL es una implementacion definida por una constante de puntero NULL 6 que en C99 se puede expresar portablemente como un valor entero 0 convertido implicita o explicitamente al tipo void 11 Tipicamente desreferenciar el puntero NULL significa intentar leer o escribir en la memoria que no se asigna esto desencadena un fallo de segmentacion o violacion de acceso Esto puede representar en si mismo para el desarrollador un fallo en el programa o se transforma en una excepcion que puede capturarse Sin embargo hay ciertas circunstancias en las que esto no es el caso Por ejemplo en modo en x86 real la direccion 0000 0000 es legible y por lo general escribible de ahi que la eliminacion de referencias de puntero nulo sea una accion perfectamente valida pero en general no deseada que puede conducir a un comportamiento indefinido pero no causa un crash en la aplicacion Ademas tener en cuenta que hay ocasiones en que la desreferenciacion NULL es intencional y bien definida como por ejemplo el codigo del BIOS escrito en C para dispositivos x86 de 16 bits en modo real puede escribir la IDT en la direccion fisica 0 de la maquina desreferenciando al puntero a NULL para la escritura Tambien es posible que el compilador optimice desde lejos el puntero de dereferencia NULL evitando un fallo de segmentacion 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 explicita que se utilizara en su lugar No se debe confundir un puntero nulo con un puntero no inicializado Un puntero nulo esta garantizado para comparar desigual a cualquier puntero que apunta a un objeto valido Sin embargo en funcion del idioma y la aplicacion un puntero no inicializado tiene o bien un valor indeterminado al azar o sin sentido o un valor especifico que no tiene porque ser necesariamente una especie de puntero nulo constante En 2009 C A R Hoare declaro 13 14 que en 1965 invento 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 invencion como un error de millones de dolares A mi error yo lo llamo error de mil millones de dolares Fue la invencion en 1965 de la referencia nula En ese momento yo estaba disenando 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 comprobacion realizada automaticamente por el compilador Pero no pude resistir la tentacion de poner en una referencia nula simplemente porque era muy facil de implementar Esto ha dado lugar a innumerables errores vulnerabilidades y fallos del sistema que probablemente han causado mil millones de dolares de dolor y danos en los ultimos cuarenta anos 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 ejecucion o la inmediata caida del programa En C no esta definido el comportamiento de eliminacion de referencias a un puntero nulo 15 Muchas implementaciones causan este tipo de codigo de lugar a que el programa se detenga con una violacion de acceso porque se elige la representacion de puntero nulo para ser una direccion 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 codigo de gestion de errores pero en la practica lo que se prefiere es asegurar que nunca ocurran tales excepciones En NET acceder a la referencia nula desencadena una excepcion NullReferenceException Aunque generalmente la captura de estos se considera una mala practica se puede atrapar este tipo de excepcion 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 union marcada que impone la manipulacion explicita del caso excepcional de hecho un puntero nulo posiblemente pueda ser visto como un puntero etiquetado con una etiqueta computarizada Puntero auto relativo EditarEl termino puntero auto relativo puede referirse a un puntero cuyo valor se interpreta como un desplazamiento desde la direccion del propio puntero por lo que si una estructura de datos M displaystyle M tiene un elemento puntero auto relativo p displaystyle p que apunta a una porcion M displaystyle M de si mismo entonces M displaystyle M puede ser reubicado en la memoria sin tener que actualizar el valor de p displaystyle p 17 La patente citada tambien utiliza el termino puntero auto relativo para significar la misma cosa Sin embargo el significado de ese termino se ha utilizado en otras formas Es de uso frecuente significar un desplazamiento de la direccion de una estructura y no de la direccion de la propia puntero cita requerida Se ha utilizado para significar un puntero que contiene su propia direccion que puede ser util para la reconstruccion en cualquier region arbitraria de la memoria una coleccion de estructuras de datos que apuntan la una a la otra 18 Puntero base EditarUn 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 direccion de comienzo del bloque al puntero base 19 Indireccion multiple EditarEn algunos lenguajes un puntero puede hacer referencia a otro puntero lo que requiere multiples operaciones de des referenciacion para llegar al valor original Mientras que cada nivel de indireccion puede anadir un costo de rendimiento es a veces necesario para proporcionar un comportamiento correcto para estructuras de datos complejas Por ejemplo en C es tipico definir una lista enlazada en terminos 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 aplicacion utiliza un puntero al primer elemento de la lista como un sustituto para la lista completa Si se anade 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 insercion de implementarse correctamente y tiene el efecto secundario deseable de eliminar el codigo 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 amp p gt next if item gt value lt p gt value break item gt next p p item El llamador hace esto insert amp head item En este caso si el valor de item es menor que el de la head se actualizara el llamador head correctamente a la direccion del nuevo item Un ejemplo basico es en el argumento argv de la funcion principal en C y C que se da en el prototipo como char argv esto es debido a que la variable argv es en si es un puntero a un arreglo de cadenas un arreglo de arreglos por lo que argv es un puntero a la cadena 0 por convencion al nombre del programa y argv es el caracter 0 de la cadena 0 Puntero a funcion EditarEn algunos lenguajes un puntero puede hacer referencia a codigo ejecutable es decir puede apuntar a una funcion metodo o procedimiento Un puntero a funcion almacenara la direccion de una funcion que sea invoca Si bien este mecanismo se puede utilizar para llamar a funciones de forma dinamica muchas veces es una tecnica favorita de virus y otros autores de software malicioso int a b x y int sum int n1 int n2 Funcion con dos parametros enteros que devuelve un valor entero int fp int int Puntero de funcion que puede apuntar a una funcion como la suma fp amp sum fp ahora apunta a la funcion suma x fp a b La funcion suma llama con argumentos a y b y sum a b La funcion suma llama con argumentos a y bPuntero salvaje EditarUn puntero salvaje es un puntero que no se ha sido inicializado es decir un puntero salvaje no ha tenido ninguna direccion asignada a el y puede provocar un fallo en el programa o comportarse de manera extrana En los lenguajes de programacion Pascal o C los punteros que no estan especificamente inicializados pueden apuntar a direcciones impredecibles en la memoria El siguiente codigo de ejemplo muestra un puntero salvaje int func void char p1 malloc sizeof char valor indefinido de algun lugar del monton char p2 puntero salvaje sin inicializar p1 a Esto esta bien asumiendo que malloc no haya devuelto NULL p2 b Asi se invoca un comportamiento indefinido Aqui p2 puede apuntar a cualquier lugar de la memoria por lo que la realizacion de la tarea p2 b puede corromper una zona desconocida de la memoria o provocar un fallo de segmentacion Simulacion utilizando un indice de matriz EditarEs posible simular el comportamiento del puntero usando un indice a un matriz normalmente unidimensional Principalmente para lenguajes que no soportan punteros de manera explicita 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 indice a ella puede considerarse como equivalente a un registro de proposito general en lenguaje ensamblador que apunta a los bytes individuales pero cuyo valor real es relativo al comienzo de la matriz no su direccion 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 aritmetica de punteros puede simularse mediante la adicion o sustraccion del indice con una sobrecarga adicional minima en comparacion con la verdadera aritmetica de punteros Incluso es teoricamente posible utilizando la tecnica anterior juntar con un simulador de juego de instrucciones adecuadas para simular cualquier codigo de maquina 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 codigo 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 comprobacion de limites por el compilador a los efectos de evitar por completo los problemas de desbordamiento de bufer o si no codificar a mano en el simulador Punteros en lenguajes de programacion EditarEn programacion es posible crear procedimientos estructuras variables constantes entre otras cosas cuando es ejecutada cada una de estas estructuras tiene una direccion en memoria es conveniente conocer este tipo de informacion cuando se trabaja con lenguajes que soportan los punteros de manera no abstracta A continuacion veremos como trabajan los punteros en variables estructuras y uniones Los punteros que apunten a estas estructuras de almacenamiento estaran dirigidos a los primeros miembros de cada estructura union o matriz Estructuras Editar Las estructuras de datos reservan segmentos en memoria separados para cada miembro esto significa que cada miembro tiene su propia direccion en memoria su propio puntero Podemos representar graficamente una estructura de datos llamada Estructura de la siguiente manera 1 1 4 Bytes A B C Miembros 0x1 0x2 0x3 Direccion Puntero base de la estructura completa Como se puede ver existen 3 metodos de tipo numerico en memoria llamados A B y C los dos primeros metodos 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 direccion de memoria de la estructura en general es igual a la direccion de su primer miembro la direccion de su segundo miembro es igual a la direccion de su primer miembro mas su tamano en bytes y la direccion del tercer miembro es igual a la direccion del primer miembro mas el tamano de los dos miembros anteriores y asi sucesivamente Uniones Editar La principal diferencia entre una union y una estructura es la memoria utilizada a diferencia de las estructuras las uniones solo utilizan la cantidad de memoria de su miembro mas grande y todos los miembros comparten una unica direccion en memoria Por ejemplo 4 Bytes A B C Miembros 0x1 Direccion 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 tambien 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 unicamente en 160 ya que tratan de traducir el valor 4000 a byte A y C son igual a 160 B 4000 el tamano total de la union es de 4 bytes debido a que los miembros comparten la misma memoria la union pesa lo mismo que su miembro con mayor reserva de memoria Matrices Editar Las matrices son casi igual que las estructuras reservan memoria para cada matriz la direccion en memoria de cada miembro es consecutiva a la suma de sus anteriores mas sus tamanos y la direccion de la matriz total es igual a la del primer miembro la unica 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 Direccion Como se puede apreciar cada miembro tiene una direccion en memoria con 4 bytes de diferencia entre si El puntero base de la matriz entera es la direccion de su primer matriz Matriz Matriz 0 Soporte en lenguajes de programacion EditarAda Editar 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 estan por defecto inicializado en i a href Null html title Null null a i y cualquier intento de acceder a la informacion a traves de un puntero a i null i provoca una excepcion En Ada los punteros se llaman tipos de acceso Ada 83 no permitia aritmetica en tipos de acceso aunque los distintos compiladores la suministren como una funcionalidad fuera del patron pero Ada 95 soporta tipos aritmeticos en tipos de acceso seguro por el paquete System Storage Elements BASIC Editar Varias versiones antiguas de BASIC para la plataforma Windows tenian soporte para STRPTR para devolver la direccion de una cadena y para VARPTR para devolver la direccion de una variable Visual Basic 5 tambien tenia soporte para OBJPTR para devolver la direccion de una interfaz de objeto y para un operador ADDRESSOF para devolver la direccion de una funcion Los tipos de todos estos son numeros enteros pero sus valores son equivalentes a estos valores por tipos de puntero Sin embargo dialectos mas recientes de BASIC como FreeBASIC o BlitzMax tienen implementaciones de puntero exhaustivas En FreeBASIC la aritmetica 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 Ademas la conversion entre ANY y cualquier otro tipo de punteros no generara 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 Editar 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 funcion y no la funcion de tipo de puntero Un tipo de puntero especial llamado el vacio puntero permite que apunta a cualquier tipo de variable no funcion pero es limitada por el hecho de que no se puede eliminar las referencias de forma directa La direccion en si a veces puede ser manipulada directamente mediante colada un puntero hacia y desde un tipo entero de tamano suficiente aunque los resultados se han definido por la implementacion y de hecho pueden causar un comportamiento indefinido mientras que los estandares anteriores a C no tengan un tipo entero que garantice que sea lo suficientemente grande C99 especifica el nombre definido uintptr ʈ typedef en lt stdint h gt pero una aplicacion no tiene por que proporcionarla C es totalmente compatible con los punteros de C y el typecasting de C Tambien es compatible con una nueva agrupacion de operadores de typecasting para ayudar a capturar a algunos casts peligrosos no deseados en tiempo de compilacion Desde C 11 la libreria estandar de C tambien 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 tambien es compatible con otro tipo de referencia muy diferente de un puntero llamado simplemente una referencia o tipo de referencia La aritmetica de punteros es decir la capacidad de modificar la direccion de destino de un puntero con operaciones aritmeticas asi como comparaciones de magnitud esta restringido por el lenguaje estandar para permanecer dentro de los limites de un solo objeto arreglo o justo despues de el porque de otro modo provocaria un comportamiento indefinido Sumando o restando de un puntero que desplaza por un multiplo del tamano del tipo de datos que apunta Por ejemplo la adicion de 1 a un puntero a valores enteros de 4 bytes incrementara el puntero por 4 Esto tiene el efecto de incrementar el puntero para senalar en el siguiente elemento en una matriz contigua de numeros enteros que muchas veces presenta un resultado previsto La aritmetica de punteros no se puede realizar en punteros void porque el tipo de vacio no tiene tamano y por lo tanto no puede anadir la direccion de punteros aunque gcc y otros compiladores realizan operaciones aritmeticas de byte de void como una extension no estandar Para trabajar directamente con bytes generalmente arrojan punteros a BYTE o unsigned char si BYTE no esta definido en la biblioteca estandar que se utiliza La aritmetica de punteros le provee al programador una unica manera de tratar con diferentes tipos sumando y restando el numero de los elementos requeridos en lugar del actual desplazamiento en bytes aunque el puntero sea char el char se define como tener siempre un tamano de un byte permite el desplazamiento del elemento de la aritmetica de punteros en la practica sea igual a un desplazamiento de bytes En particular la definicion C declara explicitamente que la sintaxis de a n que es el elemento n esimo 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 aritmetica de punteros puede ser una fuente de errores informaticos Este tiende a confundir a los programadores novatos forzandolos a diferentes contextos una expresion puede ser una aritmetica ordinaria uno o una aritmetica de punteros uno ya veces es facil confundir uno con el otro En respuesta a esto muchas lenguajes informaticos modernos de alto nivel por ejemplo Java no permiten el acceso directo a memoria utilizando direcciones Ademas el dialecto seguro de C Cyclone aborda muchos de los problemas con los punteros Vease lenguaje de programacion C de examinar mas El puntero void o void es compatible en ANSI C y C como tipo de generico puntero Un puntero a void puede almacenar una direccion a cualquier tipo de datos no funcion y en C se convierte implicitamente a cualquier otro tipo de puntero en asignacion pero se debe convertir explicitamente si es desreferenciado en linea K amp R C utiliza char para el proposito de puntero de tipo agnostico antes de ANSI C int x 4 void q amp x int p q void convierte implicitamente a int valido en C pero no en C int i p int j int q cuando se desreferencia en linea no hay conversion implicita C no permite la conversion implicita de void a otros tipos de puntero incluso en las asignaciones Esta fue una decision de diseno para evitar vaciados descuidados e incluso no deseados aunque la mayoria de los compiladores solo muestren advertencias como salida no errores cuando se encuentran con otros cast int x 4 void q amp x int p q Esto falla en C no hay conversion implicita de void int a int q cast estilo C int b static cast lt int gt q C cast En C no hay void amp 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 Editar En el lenguaje de programacion C los punteros son compatibles solo bajo ciertas condiciones cualquier bloque de codigo que incluya punteros debe ser marcada con la palabra clave unsafe Generalmente tales bloques requieren permisos de seguridad superiores a codigo pointerless que se le permitiera correr La sintaxis es esencialmente la misma que en C y la direccion 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 gestion de memoria mientras el puntero esta a su alcance lo que mantiene valida la direccion del puntero Una excepcion a esto es utilizar la estructura de IntPtr que es un equivalente administrado seguro para int y no requiere codigo no seguro Este tipo suele aparecer cuando el uso de metodos 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 metodos 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 comunicacion con codigo no administrado COBOL Editar El lenguaje de programacion 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 unica memoria asignada en el programa es el espacio para la direccion del elemento de datos normalmente una palabra de memoria individual basados en punteros En el codigo fuente del programa estos elementos de datos son utilizados como cualquier otra variable WORKING STORAGE pero sus contenidos estan indirecta e implicitamente accedidos a traves de sus punteros LINKAGE El espacio de memoria para cada senalo a objeto de datos se suelen asignar dinamicamente utilizando las sentencias CALL externos o a traves de construcciones del lenguaje extendidos embebidas como EXEC CICS o sentencias EXEC SQLLas versiones extendidas de COBOL tambien proporcionan variables de puntero declarados con clausulas 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 tambien proporcionan variables de PROCEDURE POINTER triple que son capaces de almacenar las direcciones de codigo ejecutable PL I Editar 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 comparacion con los lenguajes de programacion de su tiempo cita requerida D Editar El lenguaje de programacion D es un derivado de C y C que es totalmente compatible con los punteros de C y los typecasting de C Eiffel Editar El lenguaje Eiffel orientado a objetos soporta punteros en forma de referencias que se escriben y no permiten ningun tipo de aritmetica de punteros El estandar ECMA para Eiffel incluye un mecanismo de tipo adjunto que pretende garantizar un void seguro Fortran Editar Fortran 90 introdujo la capacidad de puntero inflexible de tipos Los punteros en Fortran contienen algo mas que una simple direccion de memoria Tambien encapsulan los limites inferior y superior de dimensiones de matriz pasos por ejemplo para soportar a las secciones de matriz arbitrarias y otros metadatos Un operador asociacion gt se utiliza para asociar un puntero a una variable que tiene un atributo TARGET El Fortran 90 tambien se puede usar la declaracion ALLOCATE para asociar un puntero a un bloque de memoria Por ejemplo el siguiente codigo podria 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 gt null end type type real list t target my real list type real list t pointer real list temp real list temp gt 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 gt real list temp next end do Fortran 2003 anade soporte para punteros de procedimiento Tambien como parte de la funcion de Interoperabilidad de C Fortran 2003 es compatible con las funciones intrinsecas para la conversion de punteros al estilo C a punteros Fortran y traseros Go Editar Go tiene punteros Su sintaxis de declaracion es equivalente a la de C pero escrito al reves terminando con el tipo A diferencia de C Go tiene la recoleccion de basura y no permite la aritmetica de punteros Al igual que en C no existen los tipos de referencia Algunos tipos incorporados como los mapas y canales estan encuadradas es decir internamente son punteros a estructuras mutables y se inicializan utilizando la funcion make Como un enfoque diferente que los tipos de referencia a la sintaxis unificada entre punteros y no punteros el operador flecha gt se ha dejado caer es posible utilizar el operador punto directamente en un puntero a un tipo de datos para acceder a un ambito o metodo 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 indireccion Java Editar A diferencia de C C o Pascal no hay representacion explicita de punteros en Java En cambio las estructuras de datos mas complejas como los objetos y las matrices se implementan utilizando referencias El lenguaje no ofrece operadores explicitos de manipulacion de punteros Aun es posible para el codigo intentar eliminar la referencia de una referencia nula puntero null sin embargo lo que resulta en una excepcion de tiempo de ejecucion que es lanzada El espacio ocupado por objetos de memoria no referenciados se recupera automaticamente recolectando la basura en tiempo de ejecucion 20 Modula 2 Editar Los punteros son fuertemente implementados como en Pascal al igual que los parametros VAR en las llamadas a procedimiento Modula 2 es mas inflexible incluso que Pascal con al menos vias de escape del sistema de tipos Algunas de las variantes de Modula 2 como Modula 3 incluyen recoleccion de basura Oberon Editar Al igual que Modula 2 los punteros estan disponibles Aun hay un menor numero de maneras de evadir el sistema de tipos y asi Oberon y sus variantes son aun mas seguros con respecto a los punteros de Modula 2 o sus variantes Al igual que con Modula 3 la recoleccion de basura es una parte de la especificacion del lenguaje Pascal Editar A diferencia de muchas lenguajes que cuentan con punteros el estandar ISO Pascal solo permite punteros para hacer referencia a las variables creadas dinamicamente que son anonimas y no les permiten referenciar estandares estaticos o variables locales 21 No tiene aritmetica de punteros Los punteros deben tambien 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 Tambien elimina algunos riesgos causados por punteros colgados pero la capacidad de dejar de lado el espacio de forma dinamica se hace referencia mediante el procedimiento estandar dispose que tiene el mismo efecto que la funcion de la libreria 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 codigo 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 estaticas o locales estandares y se puede lanzar desde un tipo puntero a otro Por otra parte la aritmetica de punteros esta restringida anadiendo o restando de un puntero se mueve por ese numero de bytes en cualquier direccion pero utilizando los procedimientos estandar Inc o Dec con que se mueve el puntero por el tamano del tipo de datos que se declara a apuntar Un puntero sin tipo tambien proporciona bajo el nombre de Pointer que es compatible con otros tipos de puntero Pauscal Editar El lenguaje de programacion Pauscal presenta un fuerte soporte de punteros permitiendo apuntar a variables estructuras procedimientos prototipos uniones e incluso clases y sus metodos Los punteros se pueden utilizar para almacenar la direccion 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 programacion de aplicaciones API externa aumentando la velocidad de ejecucion de los programas ligeramente y permitiendo que estos sean nativos del lenguaje Perl Editar El lenguaje de programacion Perl soporta punteros aunque raramente se utilizan en forma de funciones de empaquetado y desempaquetado Estos estan destinados unicamente a las interacciones simples con bibliotecas OS compiladas En todos los demas casos Perl utiliza referencias que se escriben y no permiten ningun tipo de aritmetica de punteros Estos se utilizan para construir complejas estructuras de datos 24 Vease tambien EditarDireccion constante Puntero limitado Desbordamiento de bufer Funcion puntero Puntero peligroso Puntero opaco Puntero swizzling Referencia informatica Analisis estatico de software Violacion de almacenamiento Puntero etiquetado Variable programacion Referencias Editar Donald Knuth 1974 Structured Programming with go to Statements Programacion Estructurada con sentencias goto pdf Computing Surveys en ingles 6 5 261 301 doi 10 1145 356635 356640 Archivado desde el original el 19 de mayo de 2013 Milestones in Computer Science and Information Technology IEEE Computer Society awards list Archivado desde el original el 22 de marzo de 2011 Consultado el 16 de abril de 2015 ISO IEC 9899 clausua 6 7 5 1 parrafo 1 ISO IEC 9899 clausula 6 7 8 parrafo 10 a b ISO IEC 9899 clausula 7 17 parrafo 3 NULL que expande a una implementacion definida como puntero constante nulo ISO IEC 9899 clausula 6 5 3 2 parrafo 4 footnote 87 Si un valor no valido ha sido asignada al puntero el comportamiento del operador unario es indefinido Entre los valores validos para desreferenciar un puntero por el operador unario son un puntero nulo Plauger P J Brodie Jim 1992 ANSI and ISO Standard C Programmer s Reference Redmond WA Microsoft Press pp 108 51 ISBN 1 55615 359 7 Un tipo de matriz no contiene agujeros adicionales porque todos los otros tipos de paquetes se hermetizan cuando estan compuestos en matrices en pagina 51 La referencia utiliza el parametro obsoleto coautores ayuda WG14 N1124 C Approved standards ISO IEC 9899 Programming languages C 6 de mayo de 2005 ISO IEC 9899 clausula 6 3 2 3 parrafo 4 ISO IEC 9899 clausula 6 3 2 3 parrafo 3 Stroustrup Bjarne marzo de 2001 Chapter 5 Pointers Arrays and Structures 5 1 1 Zero The C Programming Language 14ta impresion de la 3ra edicion Estados Unidos y Canada Addison Wesley p 88 ISBN 0 201 88954 4 En C ha sido popular definir un macro NULL para representar el puntero cero Debido a que en C es mas estricta la comprobacion de tipo el uso del 0 plano en lugar de cualquier macro NULL sugerido conduce a un menor numero de problemas Si se necesita definir NULL utilizar const int NULL 0 El calificador const 5 4 previene redefinicion accidental de NULL y se asegura de que NULL se puede utilizar cuando se requiere una constante Tony Hoare 2009 Null References The Billion Dollar Mistake QCon London Archivado desde el original el 19 de enero de 2009 Consultado el 15 de marzo de 2014 Tony Hoare 25 de agosto de 2009 Null References The Billion Dollar Mistake InfoQ com ISO IEC 9899 clausula 6 5 3 2 parrafo 4 The Objective C 2 0 Programming Language seccion Sending Messages to nil Plantilla Cita patente Plantilla Cita patente Based Pointers Nick Parlante 1 Stanford Computer Science Education Library pp 9 10 2000 en ingles ISO 7185 Pascal Standard unofficial copy section 6 4 4 Pointer types y subsecuentes J Welsh W J Sneeringer and C A R Hoare Ambiguities and Insecurities in Pascal Software Practice and Experience 7 pp 685 696 1977 Free Pascal Language Reference guide section 3 4 Pointers Making References Perl References and nested data structures en ingles Enlaces externos EditarPunteros en C C y correspondencia entre arrays y punteros Memoria dinamica en C malloc realloc y free Punteros y Memoria Introduccion a los punteros Biblioteca de Educacion de las Ciencias de la Computacion de Stanford 0pointer de Una lista concisa de los codigos de longitud minima que referencian a un puntero nulo en diversos lenguajes de programacion diferentes Memoria dinamica en C Operadores new y delete The C book containing pointer examples in ANSI C Joint Technical Committee ISO IEC JTC 1 Subcommittee SC 22 Working Group WG 14 8 de setiembre de 2007 International Standard ISO IEC 9899 PDF en ingles Committee Draft Datos Q118155 Multimedia Pointers computing Obtenido de https es wikipedia org w index php title Puntero informatica amp oldid 135463639, wikipedia, wiki, leyendo, leer, libro, biblioteca,

español

, española, descargar, gratis, descargar gratis, mp3, video, mp4, 3gp, jpg, jpeg, gif, png, imagen, música, canción, película, libro, juego, juegos