Programación en Pascal/Punteros

De Wikilibros, la colección de libros de texto de contenido libre.

Los punteros son una forma de manejar datos indirecta, y es útil en muchas circunstancias de la programación.

En lenguajes como C y C++, el uso de punteros de forma directa es imprescindible. En lenguajes como Java, Python, etc, el uso de punteros está en todas partes, pero oculto al programador. En concreto, en esos lenguajes, los objetos siempre son manejados como punteros, quiera o no el programador.

El motivo de necesitar usar punteros es debido a que, si no, habría muchos datos repetidos en nuestro programa, y actualizar un dato en un punto del mismo no surge efecto en otros. Demostraremos como esto es así a lo largo de este capítulo.

Hay que destacar que Pascal ofrece un compromiso medio en el uso de punteros. Si se quiere, se puede usar. Si no se quiere, no se usa. De esta manera, ni te obliga a manejarlos manualmente constantemente como en C, ni te obliga a dejar en manos del lenguaje toda la responsabilidad de su uso (como en Java), ofreciendo lo mejor de ambos mundos. Por un lado puedes programar a alto nivel, y por otro tienes acceso al sistema.

Los punteros fueron introducidos por primera vez por Turbo Pascal.

Declaración y uso[editar]

La forma básica de declarar un puntero a un tipo de de datos es la siguiente:

var
   nombre : ^tipo;

En este caso: nombre : Nombre de la variable que es un puntero. tipo : Tipo de dato al que la variable apuntará.

Ejemplo:

var
  entero : Integer;
  entero_ptr : ^Integer;

Listas enlazadas[editar]

Uno de los usos de los punteros es la creación de estructuras de datos y una de las básicas son las listas enlazadas.

Una lista enlazada es una estructura de datos basada en nodos, y cada nodo tiene al menos una referencia a otro nodo, si la lista es una lista simple cada nodo tiene una referencia al siguiente nodo de la lista y si es doblemente enlazada cada nodo tiene una referencia al anterior y al siguiente.

Existen muchas librerias para diferentes lenguajes que implementan este tipo de datos, sinembargo como la idea es aprender vamos a implementar desde cero una lista enlazada lo más genérica posible usando punteros.

Argumentos var en funciones y procedimientos[editar]

Si la sintaxis de los punteros es un poco críptica, tampoco necesitamos siempre usarla. A veces, hay que ser capaz de modificar algún dato a través del uso de un puntero, pero usando un procedimiento o función. Para eso se inventó la declaración var en la lista de argumentos:

procedure suma1 (var miNumero : Integer);
begin
  miNumero := miNumero+1;
end;

Como se ve en el ejemplo, miNumero funciona igual que un puntero, pero con una sintaxis como si no lo fuera.

Hay muchas funciones y procedimientos definidos de esa forma. Sin ir más lejos, readln lee datos del teclado y lo pone en la variable que se le ha pasado en el argumento. Si tuvieramos que redifinir readln lo haríamos de una forma parecida a esta:

procedure readln (var dondeGuardarlo : String);
begin
  ... { aquí el código que usuaríamos }
  dondeGuardarlo := ...lo que sea...;
end;

Otros usos[editar]

Los punteros también se usan para programar estructuras dinámicas (Listas y derivados, Colas, Pilas, Arboles y Grafos). Estas permiten generar estructuras que se van agrandando o empequeñeciendo en función de si quitamos o añadimos elementos a una estructura, sin embargo si tuvieras el equivalente de esa estructura de forma estática ocuparía menos, esto se debe a que las estructura debe contener punteros que apunten a otras estructuras.

Precauciones[editar]

¿Cuándo no usar punteros?[editar]

  • Normalmente no es necesario usarlo en tipos de datos básicos, como Integer, Double.... Casi siempre usarlo en estos casos no solo duplicará la memoria necesaria para almacenar la variable (ya que hay que almacenar el puntero y la variable en si misma), sino que repercutirá en mayor lentitud de proceso, ya que acceder a las variables a través de punteros es considerablemente más lento que usarlas directamente.
  • Como veremos en las siguientes lecciones, usarlo con objetos de tipo class no solo no es necesario, sino redundante. Los tipos class ya son punteros de por si.