Una introducción a los punteros para programadores
Ya sea que se dé cuenta o no, la gran mayoría de los programas que ha utilizado utilizan los punteros de alguna manera. Tal vez usted ha experimentado una Excepción de puntero nulo en algún momento. Como programador, es muy probable que el código que escriba utilice punteros, incluso si no los ha implementado usted mismo..
Hoy te mostraré cómo funcionan los punteros, por lo que quizás desees ver cómo funcionan los arrays y las listas Cómo funcionan los arrays y las listas en Python Cómo funcionan los arrays y las listas en Python Los arreglos y las listas son algunas de las estructuras de datos más útiles en la programación. - aunque pocas personas los utilizan a su máximo potencial. Leer más para una cartilla de programación. Este artículo estará más basado en la teoría de lo habitual, pero quédate con él, los punteros son muy complejos!
Código de compilación
Antes de profundizar en los punteros, debe comprender cómo se construye y ejecuta el código, tal vez ya lo sepa. Esta sección tendrá declaraciones bastante generales, cosas que se aplican a la mayoria de idiomas, pero no necesariamente todos ellos.
Vamos a llevar las cosas al comienzo. Cada computadora usa binario ¿Qué es binario? [Tecnología explicada] ¿Qué es binario? [Tecnología explicada] Dado que el binario es absolutamente fundamental para la existencia de las computadoras, parece extraño que nunca hayamos abordado el tema antes, así que hoy pensé que daría una breve descripción de qué binario ... Leer más, una serie de unos y ceros que conforman la tecnología moderna tal como la conocemos. Es extremadamente difícil codificar cualquier cosa en binario (los archivos serían muy confusos), ya que estas son las instrucciones en bruto que necesita su unidad Central de procesamiento o CPU para funcionar ¿Qué es una CPU y qué hace? ¿Qué es una CPU y qué hace? Las siglas de computación son confusas. ¿Qué es una CPU de todos modos? ¿Y necesito un procesador quad o dual-core? ¿Qué hay de AMD, o Intel? ¡Estamos aquí para ayudar a explicar la diferencia! Lee mas . Esto se conoce como Codigo de maquina.
El siguiente paso desde el código de máquina es Montaje. Este es un formato legible para los humanos. Si bien todavía es complejo para programar, es posible. El ensamblaje se compone de una serie de comandos simples para ejecutar tareas, y se conoce como nivel bajo lenguaje de programación. Es posible escribir programas complejos, pero es difícil expresar conceptos abstractos y requiere mucha consideración..
Muchos videojuegos y aplicaciones de alto rendimiento tienen parte de la lógica escrita en el ensamblaje, ya que se pueden encontrar algunos aumentos reales de velocidad si sabes lo que estás haciendo. Sin embargo, para la gran mayoría de los proyectos de programación, no necesita conocer ningún ensamblaje..
Entonces, si el código de la máquina es demasiado difícil de escribir y el ensamblaje es demasiado difícil de programar, ¿con qué se escribe el código? Aquí es donde nivel alto Los lenguajes vienen. Los lenguajes de alto nivel hacen que los programas sean fáciles de escribir. Puede programar en algo que se parezca a su idioma nativo, y es fácil expresar algoritmos complejos. Es posible que hayas oído hablar de muchos idiomas de alto nivel (y definitivamente habrás usado un programa escrito en ellos):
- BASIC
- do++
- Ceceo
¡Estos idiomas son muy antiguos ahora, y muchos se desarrollaron a principios de la década de 1950! Casi todos los lenguajes de programación modernos son un lenguaje de alto nivel, incluidos PHP y Python. Cada día se inventan más idiomas (aunque probablemente haya suficientes ahora), pero ¿cómo funciona exactamente su código si las computadoras requieren un código de máquina??
Aquí es donde entra en juego la compilación. Un compilador es un programa que convierte su código de alto nivel en un formulario que se puede ejecutar. Este podría ser otro lenguaje de alto nivel, pero generalmente es ensamblaje. Algunos idiomas (como Python o Java) convierten su código en una etapa intermedia llamada bytecode. Esto deberá volver a compilarse en una fecha posterior, lo que generalmente se realiza a pedido, como cuando se ejecuta el programa. Esto se conoce como justo a tiempo compilación, y es bastante popular.
Gestión de la memoria
Ahora que sabe cómo funcionan los lenguajes de programación, veamos la administración de memoria en lenguajes de alto nivel. Para estos ejemplos, usaré un pseudo código: código escrito no en un lenguaje específico, pero que se usa para mostrar conceptos en lugar de la sintaxis exacta. Hoy en día, esto se parecerá principalmente a C ++ ya que es el mejor lenguaje de alto nivel (en mi opinión).
Para esta sección, le ayudará si entiende cómo funciona la RAM. Una guía rápida y sucia a la memoria RAM: lo que necesita saber Una guía rápida y sucia a la memoria RAM: lo que necesita saber La RAM es un componente crucial de cada computadora , pero puede ser confuso entender si no eres un gurú de la tecnología. En este post, lo desglosamos en términos fáciles de entender. Lee mas .
La mayoría de los idiomas tienen variables, contenedores que almacenan algunos datos. Tienes que definir explícitamente el tipo de datos. Algunos lenguajes de tipo dinámico, como Python o PHP, se encargan de esto por usted, pero todavía tienen que hacerlo..
Digamos que tienes una variable:
int myNumber;
Este código declara una variable llamada mi número, y le da un tipo de datos de entero. Una vez compilado, la computadora interpreta este comando como:
“Encuentre algo de memoria vacía y reserve un espacio lo suficientemente grande como para almacenar un número entero”
Una vez que este comando se ha ejecutado, ese bit de memoria no puede ser utilizado por otro programa. Todavía no contiene ningún dato, pero está reservado para su variable myNumber.
Ahora asigne un valor a su variable:
miNúmero = 10;
Para completar esta tarea, su computadora accede a su ubicación de memoria reservada, y cambia cualquier valor que se almacene allí, a este nuevo valor.
Ahora, todo esto está muy bien, pero ¿cómo no se reservan las ubicaciones de memoria? Si los programas reservaran toda la memoria que les gusta, la memoria RAM se llenaría de inmediato, lo que constituiría una muy sistema lento.
Para evitar este problema potencial, muchos idiomas implementan un recolector de basura, utilizado para destruir variables (y, por lo tanto, liberar las ubicaciones de memoria reservadas) que se han ido fuera del ámbito.
Quizás se pregunte qué alcance tiene y por qué es tan importante. El alcance define los límites y la vida útil de las variables o cualquier memoria utilizada por un programa. Una variable es “fuera del ámbito” cuando ya no se puede acceder a él por ningún código (ahí es cuando el recolector de basura entra). Aquí hay un ejemplo:
function maths () int firstNumber = 1; int secondNumber = 2; imprimir (firstNumber + secondNumber); // no trabajará
Este ejemplo no se compilará. La variable primer número está dentro de la matemáticas Función, por lo que es su alcance. No se puede acceder desde fuera de la función en la que se ha declarado.. Este es un concepto de programación importante., Y entenderlo es crucial para trabajar con punteros..
Esta forma de manejar la memoria se llama apilar. Es la forma en que funciona la gran mayoría de los programas. No tienes que entender los indicadores para usarlo, y está bastante bien estructurado. La desventaja de la pila es la velocidad. Como la computadora tiene que asignar memoria, hacer un seguimiento de las variables y ejecutar la recolección de basura, hay una pequeña sobrecarga. Esto está bien para programas más pequeños, pero ¿qué pasa con las tareas de alto rendimiento o las aplicaciones de datos pesados??
Introduzca: punteros.
Punteros
En la superficie, los punteros suenan simples. Hacen referencia (apunta a) una ubicación en la memoria. Esto puede no parecer diferente a “regular” Variables en la pila, pero créeme, hay una gran diferencia. Los punteros se almacenan en el montón. Esto es lo opuesto a la pila: está menos organizado, pero es mucho más rápido.
Veamos cómo se asignan las variables en la pila:
int numberOne = 1; int numberTwo = numberOne;
Esta es una sintaxis simple; La variable número dos contiene el numero uno. Su valor se copia durante la asignación de la número uno variable.
Si quisieras conseguir el dirección de memoria de una variable, en lugar de su valor, tiene que usar el signo "&" (&). Esto se llama Dirección de operador, y es una parte esencial de su kit de herramientas de puntero.
int numberOne = 1; int numberTwo = & numberOne;
Ahora el número dos variable puntos a una ubicación de memoria, en lugar de copiar el número uno en su propia ubicación de memoria nueva. Si tuviera que generar esta variable, no sería el número uno (aunque esté almacenado en la ubicación de la memoria). Produciría su ubicación de memoria (probablemente algo así como 2167, aunque varía según el sistema y la RAM disponible). Para acceder al valor almacenado en un puntero, en lugar de la ubicación de la memoria, debe desreferencia el puntero Esto accede directamente al valor, que sería el número uno en este caso. Así es como se hace referencia a un puntero:
int numberTwo = * numberOne;
los operador de desreferencia es un asterisco (*).
Este puede ser un concepto difícil de entender, así que repasémoslo nuevamente:
- los Dirección de operador (&) almacena la dirección de memoria.
- los operador de desreferencia (*) accede al valor.
La sintaxis cambia ligeramente al declarar punteros:
int * myPointer;
El tipo de datos de En t Aquí se refiere al tipo de datos del puntero. puntos a, y no el tipo del puntero en sí.
Ahora que sabes qué son los punteros, ¡puedes hacer algunos trucos realmente ingeniosos con ellos! Cuando se utiliza la memoria, su sistema operativo se inicia secuencialmente. Se puede pensar en la memoria RAM como palomas. Muchos agujeros para almacenar algo, solo uno puede ser usado a la vez. La diferencia aquí es que todos estos agujeros de palomas están numerados. Cuando asigna memoria, su sistema operativo comienza en el número más bajo y funciona. Nunca saltará entre números al azar.
Cuando trabaje con punteros, si ha asignado una matriz, puede navegar fácilmente al siguiente elemento simplemente incrementando su puntero.
Aquí es donde se pone interesante. Cuando pasa valores a una función (utilizando variables almacenadas en la pila), estos valores se copian en su función. Si estas son variables grandes, tu programa ahora las está almacenando dos veces. Cuando su función haya finalizado, es posible que necesite una forma de devolver estos valores. Por lo general, las funciones solo pueden devolver una cosa, entonces, ¿qué sucede si desea devolver dos, tres o cuatro cosas??
Si pasa un puntero a su función, solo se copiará la dirección de la memoria (que es pequeña). ¡Esto ahorra a tu CPU un montón de trabajo! Tal vez su puntero apunte a una gran matriz de imágenes; no solo su función puede funcionar exactamente con los mismos datos almacenados en la misma ubicación de memoria, sino que, una vez que se realiza, no es necesario devolver nada. ordenado!
Pero tienes que ser muy cuidadoso. Los punteros aún pueden salir del alcance y ser recolectados por el recolector de basura. Los valores almacenados en la memoria, sin embargo, no se recogen. Esto se llama una pérdida de memoria. Ya no se puede acceder a los datos (ya que los punteros se han destruido), pero aún se está utilizando la memoria. Esta es una razón común para que muchos programas se bloqueen, y puede fallar espectacularmente si hay una gran cantidad de datos. La mayoría de las veces, su sistema operativo anulará su programa si tiene una gran pérdida (usando más RAM de la que tiene el sistema), pero eso no es deseable.
La depuración de los punteros puede ser una pesadilla, especialmente si está trabajando con grandes cantidades de datos, o trabajando en bucles. Sus desventajas y la dificultad de entender realmente valen la pena las concesiones que obtiene en el desempeño. Aunque recuerde, puede que no siempre sean necesarios..
Es todo por hoy. Espero que hayas aprendido algo útil sobre un tema complejo. Por supuesto, no hemos cubierto todo lo que hay que saber, es un tema muy complejo. Si está interesado en aprender más, le recomiendo C ++ en 24 horas.
Si esto fue un poco complejo, eche un vistazo a nuestra guía de lenguajes de programación más fáciles. 6 Lenguajes de programación más fáciles de aprender para principiantes. 6 Lenguajes de programación más fáciles de aprender para principiantes. Proceso de edificación. Aquí están los seis lenguajes de programación más fáciles para principiantes. Lee mas .
¿Aprendiste cómo funcionan los punteros hoy? ¿Tienes algún consejo o truco que quieras compartir con otros programadores? Salta a los comentarios y comparte tus pensamientos a continuación.!
Explorar más sobre: Programación.