Punteros

4.
P
u
n
t
e
r
o
s

## Introduccion

Los temas que englobamos en el presente texto, nos parecieron pertinentes para dar una explicación óptima de cómo funcionan los punteros (apuntadores), como es que también el espacio en memoria está direccionado en Hexadecimal, porque incluso nos es importante aprenderlo, también la utilidad de un puntero (apuntador) como parte de otras estructuras más complejas y no solo en variables simples, además de que tratamos de hacer que este tema sea mejor asimilado y que este conocimiento sea aplicable para todos.
Los apuntadores, son herramientas básicas en la programación que nos permiten acceder de forma directa al espacio de almacenamiento en memoria, lo cual hemos de mencionar nos facilita en lo sumo muchos procesos, son piezas esenciales en otras estructuras de datos como las colas e incluso los grafos, este tema es en lo sumo extenso. La elaboración de este trabajo nos hará entender como un simple cambio de tipo de dato (conversión) se vale de esta herramienta para poder ser realizado, y como es que acceder directamente a un espacio de memoria de una variable dentro del programa puede ser tan útil. Desde un punto de vista general y conforme a lo investigado para la realización de este trabajo, podemos ver que es un tema bastante importante del cual hemos podido aprender distintas cosas que nos pueden servir como apoyo, para construirnos como mejores profesionales en el ámbito de la programación.
Aprender acerca de los apuntadores e incluso sobre todas estructuras de datos, es similar a entender como son las cosas desde adentro, por ejemplo en la primaria habíamos aprendido que tenemos 5 sentidos, el tacto, el gusto, la vista, el olfato y oído, pero, con posterioridad aprendimos como es que estos funcionan de manera interna, es decir podemos tener gusto porque la lengua tiene papilas gustativas, y estas a su vez actúan como sensores capaces de reconocer lo que conocemos como salado, dulce, amargo o ácido. Esto supone una evolución en nuestros conocimientos al entrar en algo más profundo, no es que no conozcamos esto en lo más mínimo, sino que los conocimientos que obtendremos de estructuras de datos, y en particular de apuntadores, nos hace entender cómo funciona la memoria RAM, y como entenderla es una gran oportunidad para mejorar como programadores.

## Desarrollo temático

Un apuntador, es una herramienta muy útil en la programación ya que hace que el manejo de la información almacenada en la memoria RAM, sea más accesible y manipulable, esto lo convierte en una estructura de datos por excelencia, e inclusive son utilizados para almacenar en la memoria de manera dinámica. En nuestra investigación, hemos encontrado que varios autores lo definen de manera similar, Joyanes lo define de esta manera (Joyanes, 2008) Un puntero (apuntador) es una variable cuyo valor es la dirección o posición de otra variable. Su definición nos parece satisfactoria, y (Francisco Javier Gil Chica dfists, marzo 2010). Los punteros apuntan a variables. Pero un puntero es una clase de variable, luego nada impide que un puntero apunte a otro. Así que podemos tener punteros que apuntan a punteros, punteros que apuntan a punteros que apuntan a punteros y así sucesivamente, está es una definición muy interesante porque muestra como es que el puntero “apunta” es decir nos da una referencia a un espacio de la memoria. También en (Kanagusico, 2011) Un apuntador o puntero es una variable que contiene una dirección de memoria. Esa dirección es la posición de un objeto (normalmente una variable) en memoria. Es una concepción diferente ya que da pauta a pensar que direcciones de objetos diferentes a las variables pueden ser apuntadas. La definición de Reyes Cortes, es la siguiente: Los apuntadores, también conocidos como variables tipo puntero contienen direcciones de memoria de otra variable, para acceder y manipular dichas localidades de memoria; la variable puntero a través de la dirección de memoria puede leer y escribir información. Es decir, esta apuntando a esa variable.¹ Es la más completa y representativa y es la que se tomará en cuenta durante toda la redacción de este escrito, no queremos decir que las otras no son válidas pero, con fines didácticos está es más representativa. Pero para poder ampliar el concepto nosotros lo definiremos como:
“Los punteros (apuntadores), son también conocidos como variables tipo puntero contienen direcciones de memoria de un objeto (normalmente una variable), para acceder y manipular dichas localidades de memoria; la variable puntero a través de la dirección de memoria puede leer y escribir información. Es decir, está apuntando a esa variable.”

### Características de los apuntadores

Un apuntador posee algunas características como las siguientes:
• PARÁMETROS POR REFERENCIA: en vez de una copia del valor de un parámetro, con apuntadores pasas la dirección del objeto y por lo tanto, la función puede alterar el objeto "externo". Esto tiene que ver con el uso en las funciones, pero esto lo analizaremos más adelante.
• APUNTADOR UNIVERSAL (VOID *): declara un apuntador genérico, apunta a cualquier tipo de objeto.
• OPERADORES PERMITIDOS: asignar, sumar con contantes, restar, comparar, convertir y manejo de bits.
• OPERADORES PROHIBIDOS: multiplicar, dividir y sumar dos o más apuntadores.
• APUNTADOR NULO: valor reservado, dirección cero, significa "apuntador vacío", definido en NULL == (void *)0
• PELIGRO: Un apuntador puede accesar indirectamente el contenido de un objeto.
• PRECAUCION: Todo apuntador debe inicializarse antes de usarse.

## Como usar punteros

### *Punteros

Los punteros son un tipo especial de variable que contienen direcciones de memoria así como sus contenidos o variables. Por ser una variable aunque de tipo especial, su declaración no varía de gran forma con lo estudiado hasta el momento.
*Un apuntador puede ser la dirección de otra variable.
La declaración de la variable apuntador se hace:
Tipo *nombre_de_la_variable;
Se agrega * como prefijo al declarar una variable de tipo apuntador. El tipo de dato define la estructura a la que va a hacer referencia el apuntador.

### -Operadores de apuntador

& operador de dirección o referencia. Devuelve la dirección de memoria de la variable. * operador de indirección o “desreferencia”. Devuelve el valor situado en la dirección del operando. Se dice que da acceso a la variable que señala el apuntador.

### Aclaraciones pertinentes

Como ya habíamos mencionado antes la estructura para declarar un puntero es:
Tipo de dato *nombre;
Pueden ser inicializados a 0, NULL o una dirección especifica (cuyo formato se presenta en hexadecimal) Un puntero con valor NULL apunta a nada.
Si se desea declarar varios punteros en la misma línea C# permite hacerlo de la siguiente manera:
Int* p1,p2,p3;
Luego no se podrá utilizar un puntero de tipo int con variable de otro tipo por ejemplo char o float. En esencia, los punteros deben declararse con el mismo tipo de dato al que apuntan.

### -Operadores aritméticos

Las únicas operaciones que se pueden hacer con variables de apuntador son la suma y la resta, de manera que los operadores validos son:
+ suma
- resta
++ incremento
-- decremento
La aritmética de operadores no suma las direcciones de memoria si no sus elementos. Esto quiere decir que si yo incremento en uno a una variable apuntador a entero no se incrementa un byte, sino dos bytes porque es el espacio que ocupa un entero en la memoria.
Pero en realidad las operaciones que podemos realizar únicamente para recorrer la memoria son suma y resta.
Las dos operaciones aritméticas que se pueden usar como punteros son la suma y la resta. Cuando se incrementa un puntero, apunta a la posición de memoria del siguiente elemento de su tipo base. Cada vez que se reduce, apunta a la posición del elemento anterior.
Un apuntador es un objeto que hace referencia a otro objeto.
Un objeto apuntador contiene la dirección de la memoria hacia la que apunta. Por ejemplo:

### -Declaración de apuntador.

Tipo de dato* nombre;
Tipo de dato* nombre=&objeto;

## Errores comunes al usar punteros

### Problemas con los punteros.

Un puntero con un valor erróneo es MUY PELIGROSO, y el ERROR más DIFÍCIL DE DEPURAR, porque en compilación NO SE DETECTA, y los errores tras ejecutar pueden DESPISTAR. Hay que hacer caso a los AVISOS (WARNINGS) ya que una sospecha sobre un PUNTERO puede provocar un gravísimo error en ejecución.

### Ejemplo de puntero que no apunta al tipo correcto:

El tipo base del puntero determina el tipo de datos al que apunta el puntero y por tanto es el que le indica al compilador cuantos bytes debe transferir para cualquier asignación que usa un puntero. Como podemos asignar cualquier dirección a un puntero, no se produce error cuando asignamos a un puntero, la dirección de una variable de un tipo distinto.
El error es debido a que p es un puntero a int y hacemos que apunte a un float.
El valor correcto es: 55.400000.
Valor apuntado (como float): 508524232706.400024
Valor apuntado (como int) : -26214

### Ejemplo de puntero no inicializado:

Ponemos el valor de i (50) en la dirección de memoria a la que apunta p, pero ¿a dónde apunta p?. Si p apunta a una zona libre no hay problema, pero si es a una zona donde hay datos entonces habrá problemas. Lo peor en este caso es que el compilador no muestra ningún mensaje de error o de aviso.

### Ejemplo de puntero usado de forma incorrecta:

Este error suele ocurrir cuando olvidamos poner el operador de dirección (&). Por ejemplo, consideremos el siguiente programa: Lo correcto sería haber escrito p = &i; El error es debido a que hacemos que p apunte a la dir 50 de memoria, en vez de a la dir de memoria donde se encuentra la variable i.

## Punteros como parte de otras estructuras de datos

### Apuntadores en pilas , colas y listas

Para comprender la relación entre los apuntadores en las pilas y colas es necesario saber primeramente la definición de pila y cola así como el de nodo Y por supuesto una definición de apuntador o puntero.

### Definiciones:

• Puntero o apuntador: Un puntero es una variable que contiene una dirección de memoria. Esta dirección es la posición de otra variable. Se dice que la variable puntero “apunta a la segunda”. Es utilizado como los cursores para la implementación de estructuras encadenadas, por ejemplo, listas, pilas, colas, árboles, etc. A diferencia del cursor, el alocamiento de la memoria se realiza al momento de necesitarse el espacio, cuando va a ser ocupado, por eso se denomina alocamiento “dinámico”.
• Nodo(TDA): estructura que contiene un elemento (El dato que se desea guardar en la estructura), y una referencia a otro nodo. De esta forma es posible encadenar los nodos pudiendo guardar una cantidad ilimitada de elementos.
• Pila: una estructura de datos en la cual los elementos almacenados en la misma se agregan y se sacan del mismo lugar, llamado el tope de la pila. El tope es el único lugar a partir del cual se pueden acceder a los elementos de la estructura. Esta característica hace que el último elemento en ser insertado en la pila es el primero en salir. Este tipo de estructuras se denominan LIFO (Last In First Out).
• Cola: estructura de datos en la cual los elementos almacenados en la misma se agregan al final y se sacan del principio de la cola. Esta característica hace que el primer elemento insertado en la cola es el primero en salir, como en cualquier cola de la realidad (en un banco, en el cine, en el colectivo). Este tipo de estructuras se denominan FIFO (First In First Out).
• Listas: a estructura de datos en la cual los elementos almacenados en la misma pueden ser agregados, borrados y accedidos sin restricciones, en cualquier punto de la estructura. A diferencia de las pilas y las colas, en las listas se pueden ver todos los elementos de la estructura, permitiendo realizar recorridos y consultas de los datos. De la estructura de una lista se distinguen dos elementos: el principio, a partir del cual se inician las búsquedas y recorridos; y el corriente, elemento de referencia en la lista, a partir del cual se realizan borrados, inserciones y modificaciones
Ahora ya con una breve definición se puede comprender un poco mas sobre las pilas,colas y listas,estas pueden manejarse mejor con la implementación de los nodos y lo punteros, ya que en las definiciones vimos
“un puntero es una variable que contiene una dirección de memoria. Esta dirección es la posición de otra variable.”- Lic. Gustavo Carolo
Y un nodo:” estructura que contiene un elemento (El dato que se desea guardar en la estructura), y una referencia a otro nodo”- Lic. Gustavo Carolo
Esto es que el nodo es el dato que se desea guardar pero si este dato se desea que tenga más espacio se puede utilizar junto a un puntero de esta manera cuando sea necesario dicho dato del nodo podrá tener más espacio cuando sea requerido.

### Pilas con nodo y puntero:

“Para la implementación de la pila, es necesario que el tipo de dato contenga una referencia al nodo tope de la pila. Luego, cada nodo tendrá una referencia al nodo que le siguiente. De esta manera se formara una cadena con inicio en el nodo tope y que finaliza en el último elemento de la pila, cuyo nodo no referenciará a ningún elemento.”
Un ejemplo es la pila de platos o de vasos ,el elemento que este hasta arriba tendrá un nodo o un espacio que estará vinculado a los que estén debajo y cada uno tendrá a su vez un nodo, si un nodo tuviera un puntero esto querrá decir que cada que apilen un vaso no habrá peligro de que en un espacio pequeño se rompan o no quepan los vasos o platos ya que el puntero les generara espacio para que puedan seguir entrando.

### Cola con nodo y puntero:

“Para implementar una cola será necesario que la estructura contenga una referencia al primer nodo de la cola y otra al último nodo. Luego, desde el primer nodo de la cola, se irán encadenando los demás nodos, hasta el último.”
Un ejemplo son las colas como las del banco ,el nodo que contendrá el puntero o la variable seria la persona que esta primero al faltar espacio en la parte trasera haría que la persona de adelante avance mas para generar espacio ,asi al ser atendida crea espacio para las personas que van llegando.

### Lista con nodo y puntero:

“El tipo de dato abstracto lista, contendrá dos referencias a nodos de la lista. La primera corresponderá al primer nodo de la lista. La otra hará referencia al elemento actual o corriente de la lista. Luego, los nodos de la lista se irán encadenando uno a uno hasta el último elemento. Hay que tener en cuenta que el elemento corriente puede ser cualquiera de la lista, y que ira variando según la primitiva que se utilice.”

## Ventajas y desventajas del uso de punteros.

Variable que almacena una dirección de memoria. Una variable de este tipo "apunta" o hace referencia a uno o más objetos Desde su declaración "sabe" el tipo de objetos a que hace referencia.
Los apuntadores, son por tanto una herramienta avanzada de programación que nos permite crear un sinfín de posibilidades dependiendo del uso que se le desee dar, es decir, que puede fungir un papel determinado respecto al propósito del programa en cuestión, y, como toda buena herramienta dentro de la programación, esta tiene sus capacidades a favor para con el programador, y sus capacidades en contra con el mismo, las cuales analizaremos en el siguiente apartado.

### Beneficios y Ventajas:

• Generar elementos bajo demanda, i.e. asignación dinámica de memoria.
• Manipular y recorrer grandes espacios de memoria.
• Generar estructuras de datos complejas
• Parámetros de entrada/salida para funciones, i.e. parámetros por referencia.
• Ofrecen potencia y la flexibilidad en C
• Se pueden tener apuntadores a cualquier tipo de variable.
• También son útiles para pasarle parámetros a las funciones de tal modo que les permiten modificar y regresar valores a la rutina que las llama.
• Es la única forma de expresar algunos cálculos, dado que generan un código compacto y eficiente, pues son una herramienta muy poderosa.
• Declarar e inicializar apuntadores es bastante fácil.
• Existe una relación estrecha entre los punteros y los arreglos. Por ejemplo, en C, un nombre de un arreglo es un índice a la dirección de comienzo del arreglo. En esencia, el nombre de un arreglo es un puntero al arreglo.
• Mientras un programa está corriendo todas las variables se guardan en memoria, cada una tiene su dirección o localidad única, función que sólo los apuntadores pueden proveer.
• Poseen una programación eficaz a nivel de máquina cuando se maneja la memoria del ordenador.
• Permiten también, realizar operaciones realizar operaciones de asignación dinámica de memoria.
• De igual manera, permiten efectuar operaciones con estructuras de datos dinámicas.
• Permiten crear ciertos tipos de estructuras de datos como listas encadenadas, cuyo diseño hace que sean muy eficientes a la hora de, por poner un ejemplo, insertar un nuevo elemento a la misma.

### Dificultades y Desventajas:

• Programación avanzada, caótica y/o complicada.
• Programación más susceptible de errores, por ende, es muy difíciles de depurar.
• Dificultad para leer y comprender código.
• A excepción de C, los apuntadores no son muy versátiles en otros lenguajes.
• Un apuntador a cualquier tipo de variables es una dirección en memoria, la cual es una dirección entera, pero un apuntador no es un entero, y por tanto, hay que programar su transformación.
• El manejo complicado del almacenamiento.
• Alta sobrecarga por el movimiento, compilación y depuración de líneas.
• No asignar un apuntador a una dirección de memoria antes de usarlo, significa un error fatal.
• Su uso debe ser con extrema precaución, dado que pueden provocar fallos en el programa muy difíciles de localizar, y estos suelen ser por una asignación incorrecta o bien, una dirección del mismo sentido.
Ahora bien, los punteros son una herramienta útil en el manejo de la programación, pues nos permiten realizar una gran cantidad de tareas con facilidad, cosa que podríamos hacer con mucho mayor esfuerzo y por ende, un código considerablemente más extenso en contraste con uno que use apuntadores, a esto se le conoce como “fuerza innecesaria”, pues no hay necesidad de trabajar de más cuando una herramienta nos permite hacerlo con más versatilidad.

## Punteros y almacenamiento

El almacenamiento es la capacidad de guardar datos que tiene un dispositivo electrónico. Conocemos al menos 3 tipos de almacenamiento, el primario(la memoria RAM), que está conectada directamente con el CPU, el secundario(el disco duro), el terciario que son los dispositivos de almacenamiento fuera de linea que pueden ser retirados en cualquier momento, sin provocar algún daño en el sistema.
La capacidad de almacenamiento esta definida por la memoria.

### Memoria principal

La memoría principal se define como: La memoria primaria, está directamente conectada a la CPU del ordenador. Debe estar presente para que la CPU efectúe cualquier función. El almacenamiento primario consta de la memoria primaria del sistema; contiene los programas en ejecución y los datos con que operan. Se puede transferir información muy rápidamente (típicamente en menos de 100 ciclos de reloj2) entre un registro del microprocesador y localizaciones del almacenamiento principal. En las computadoras modernas se usan memorias de acceso aleatorio basadas en electrónica del estado sólido, que está directamente conectada a la CPU a través de buses de direcciones, datos y control.
El almacenamiento lleva por principal requisito que cualquiera de sus localidades debe ser directamente direccionable, esto es, todo dato contenido en memoria debe poder encontrarse basándose en su dirección. Es por esto que los registros del procesador no pueden considerarse almacenamiento primario. Las referencias a éstos se efectúan por nombre, de forma directa, y no por dirección. Los registros representan el estado actual del cómputo y los datos utilizados inmediatamente, pero no pueden almacenar un programa (sólo apuntar al lugar de ejecución actual).
La gran diferencia de velocidad entre el procesador y la memoria primaria dio origen a la memoria caché. Esta es una memoria de muy alta velocidad, típicamente entre 10 y 100 veces más que la memoria primaria, y se emplea para mejorar la eficiencia o rendimiento del CPU. Parte de la información de la memoria principal se duplica en la memoria caché. Comparada con los registros, la caché es ligeramente más lenta, pero de mayor capacidad. Sin embargo, es más rápida, aunque de mucha menor capacidad que la memoria principal.
Algunos autores3 presentan a la memoria caché como una jerarquía aparte, sin embargo, al no ser memoria directamente direccionable (guarda estrictamente copias de la información disponible en la memoria principal), es común presentarla como parte funcional del almacenamiento primario.

### Memoria dinámica

La memoria dinámica se refiere a aquella memoria que no puede ser definida ya que no se conoce o no se tiene idea del número de la variable a considerarse, la solución a este problema es la memoria dinámica que permite solicitar memoria en tiempo de ejecución, por lo que cuanta más memoria se necesite, más se solicita al sistema operativo, que es el conjunto de los programas que administran los recursos y controlan su funcionamiento. El sistema operativo maneja la memoria gracias al uso de punteros, por la misma naturaleza del proceso nos impide conocer el tamaño de la memoria necesaria en el momento de compilar.
Un dato importante es que como tal este tipo de datos se crean y se destruyen mientras se ejecuta el programa y por lo tanto la estructura de datos se va dimensionando de forma precisa a los requerimientos del programa, evitándonos así perder datos o desperdiciar memoria si hubiéramos tratado de definir la cantidad de memoria a utilizar en el momento de compilar el programa.

### Ejemplo

Cuando se crea un programa en el que es necesario manejar memoria dinámica el sistema operativo divide el programa en cuatro partes que son: texto, datos (estáticos), pila y una zona libre o heap. En la última parte es donde queda la memoria libre para poder utilizarla de forma dinámica. En el momento de la ejecución habrá tanto partes libres como partes asignadas al proceso por lo cual si no se liberan las partes utilizadas de la memoria y que han quedado inservibles es posible que se «agote» esta parte y por lo tanto la fuente de la memoria dinámica. También la pila cambia su tamaño dinámicamente, pero esto no depende del programador sino del sistema operativo.

## Memoria virtual

La memoria virtual es una técnica de gestión de la memoria que permite que el sistema operativo disponga, tanto para el software de usuario como para sí mismo, de mayor cantidad de memoria que esté disponible físicamente. La mayoría de los ordenadores tienen cuatro tipos de memoria: registros en la CPU, la memoria caché (tanto dentro como fuera del CPU), la memoria RAM y el disco duro. En ese orden, van de menor capacidad y mayor velocidad a mayor capacidad y menor velocidad.
Muchas aplicaciones requieren acceso a más información (código y datos) que la que se puede mantener en memoria física. Esto es así sobre todo cuando el sistema operativo permite múltiples procesos y aplicaciones ejecutándose simultáneamente. Una solución al problema de necesitar mayor cantidad de memoria de la que se posee consiste en que las aplicaciones mantengan parte de su información en disco, moviéndola a la memoria principal cuando sea necesario. Hay varias formas de hacer esto.
Una opción es que la aplicación misma sea responsable de decidir qué información será guardada en cada sitio (segmentación), y de traerla y llevarla. La desventaja de esto, además de la dificultad en el diseño e implementación del programa, es que es muy probable que los intereses sobre la memoria de dos o varios programas generen conflictos entre sí: cada programador podría realizar su diseño teniendo en cuenta que es el único programa ejecutándose en el sistema. La alternativa es usar memoria virtual, donde la combinación entre hardware especial y el sistema operativo hace uso de la memoria principal y la secundaria para hacer parecer que el ordenador tiene mucha más memoria principal (RAM) que la que realmente posee. Este método es invisible a los procesos. La cantidad de memoria máxima que se puede hacer ver que hay tiene que ver con las características del procesador.
Por ejemplo, en un sistema de 32 bits, el máximo es 232, lo que da 4096 Megabytes (4 Gigabytes). Todo esto hace el trabajo del programador de aplicaciones mucho más fácil, al poder ignorar completamente la necesidad de mover datos entre los distintos espacios de memoria.

## Hexadecimal y su relación con el almacenamiento.

### Sistema Hexadecimal

Un gran problema con el sistema binario es la verbosidad. Para representar el valor 20210 se requieren ocho dígitos binarios, la versión decimal sólo requiere de tres dígitos y por lo tanto los números se representan en forma mucho más compacta con respecto al sistema numérico binario. Desafortunadamente las computadoras trabajan en sistema binario y aunque es posible hacer la conversión entre decimal y binario, ya vimos que no es precisamente una tarea cómoda. El sistema de numeración hexadecimal, o sea de base 16, resuelve este problema (es común abreviar hexadecimal como hex aunque hex significa base seis y no base dieciseis). El sistema hexadecimal es compacto y nos proporciona un mecanismo sencillo de conversión hacia el formato binario, debido a ésto, la mayoría del equipo de cómputo actual utiliza el sistema numérico hexadecimal. Como la base del sistema hexadecimal es 16, cada dígito a la izquierda del punto hexadecimal representa tantas veces un valor sucesivo potencia de 16, por ejemplo, el número 123416 es igual a:
1*163 + 2*162 + 3*161 + 4*160
lo que da como resultado:
4096 + 512 + 48 + 4 = 466010
Cada dígito hexadecimal puede representar uno de dieciseis valores entre 0 y 1510. Como sólo tenemos diez dígitos decimales, necesitamos inventar seis dígitos adicionales para representar los valores entre 1010 y 1510. En lugar de crear nuevos simbolos para estos dígitos, utilizamos las letras A a la F. La conversión entre hexadecimal y binario es sencilla, considere la siguiente tabla:
Esta tabla contiene toda la información necesaria para convertir de binario a hexadecimal y viceversa. Para convertir un número hexadecimal en binario, simplemente sustituya los correspondientes cuatro bits para cada dígito hexadecimal, por ejemplo, para convertir 0ABCDh en un valor binario:

## CONCLUSIÓN

Como podemos observar, los punteros son una herramienta de vital importancia dentro de la programación, pues facilitan un sinfín de tareas al programador según el objetivo que este posea al momento de trabajar en ello, pues que sus capacidades de manipular los datos y usarlos de forma versátil dentro de las propias Estructuras de Datos es increíble. Por otro lado, sabemos que nada es perfecto, y los apuntadores no son la excepción a esta regla, puesto que, para muestra basta un botón, y estos pueden terminar por causar una gran problemática dentro del programa si no se usan adecuadamente; los punteros requieren de una especificación muy concisa y específica, de modo que estén completamente bien definidos, y es precisamente este aspecto el que los vuelve un tanto problemáticos.
De manera general, los punteros son armas poderosas en manos de un programador con capacidades considerablemente buenas, y su aprendizaje requiere de práctica, por lo que es bueno familiarizarse con ellos en propósitos simples antes de atreverse a adentrarse con ellos en programas más complejos.

## REFERENCIAS BIBLIOGRAFICAS Y ELECTRONICAS

• Pacheco Alberto.,(29/May/2007) "Apuntadores y Estructuras" Programación C ,ExpoVision, ITCH, http://expo.itch.edu.mx/view.php?f=c_51
• Fundamentos de programación, estructuras de datos capítulo 5 , http://robotica.uv.es/pub/Libro/PDFs/CAPI5.pdf
• Lic. Gustavo Carolo(Enero 2005) Algoritmos y Programación II: Guía de Estudio – Listas, Pilas y Colas, https://algo2.files.wordpress.com/2008/08/ayp2_listas_pilas_y_colas.pdf
• https://es.wikipedia.org/wiki/Variable_(programaci%C3%B3n)
• LIC. JAVIER JIMÉNEZ PACHECO, APUNTADORES, http://azul2.bnct.ipn.mx/academia/apuntes/apuntadores.pdf
• Pacheco Alberto.,(2007) "Apuntadores y Estructuras" Universidad Tecnológica De Chihuahua
• Apuntadores(punteros). (20 de agosto de 2017) s.f PE7(Apuntadores) http://www.utm.mx/~mgarcia/PE7(Apuntadores).pdf
• Como programar en C# segunda edición 2007 Deitel,Harvey M. y Paul J. Deitel
• Ciclo instrucción.(20 de agosto de 2017) Wikipedia https://es.wikipedia.org/wiki/Ciclo_de_instrucci%C3%B3n
• -Estructuras de datos con C++, Objetos, abstracciones y diseño, Eliot B. Koffman / Paul A.T. Wolfgang, Procesamiento de datos. (20 de agosto de 2017) s.f. Monografias.com Leer más: http://www.monografias.com/trabajos90/procesamiento-de-datos/procesamiento-de-datos.shtml#ixzz4qM00eaq8
• http://programacion1abundiz.blogspot.mx/2009/09/sistema-numerico-octal-y-hexadecimal.html
• Memoria virtual (21 de agosto de 2017) s.f. https://es.wikipedia.org/wiki/Memoria_virtual
• Memoria dinamica. (20 de agosto de 2017) s.f. Memoría Dinámica https://es.wikipedia.org/wiki/Memoria_din%C3%A1mica_(programaci%C3%B3n) Memoria (informática)(20 de agosto de 2017) Memoria (informática) https://es.wikipedia.org/wiki/Memoria_(inform%C3%A1tica)

## COMPLEMENTOS

Tutorial C++ 24. Punteros a estructuras