23 - Procedimientos: parámetros por referencia

Vimos en el concepto anterior los parámetros por valor, ahora veremos que hay una segunda forma de definir parámetros que es por referencia.

Un parámetro por referencia tiene por objetivo modificar el contenido de una variable que se le envía a un procedimiento.

Si por medio de un parámetro por valor llega un dato a un procedimiento, por un parámetro por referencia se retorna y sale un dato de un procedimiento.

La sintaxis para definir un parámetro por referencia es agregar la palabra clave var previo al nombre del parámetro.

Implementaremos un problema elemental para ver la deferencia entre un parámetro por valor y un parámetro por referencia:

Problema 1

Proyecto92

program Proyecto92;

{$APPTYPE CONSOLE}

procedure procedimiento1(x: Integer);
Begin
  WriteLn('Parámetro recibido por valor:', x);
  x := 100;
End;

procedure procedimiento2(var x: Integer);
Begin
  WriteLn('Parámetro recibido por referencia:', x);
  x := 100;
End;


var
  valor: Integer;

begin
  valor := 1;
  procedimiento1(valor);
  WriteLn('Contenido de la variable valor:', valor);
  procedimiento2(valor);
  WriteLn('Contenido de la variable valor:', valor);
  ReadLn;
end.

El procedimiento1 recibe por valor un parámetro, si dentro del mismo cambiamos su contenido asignándole otro dato el mismo no se ve reflejado en la variable que le pasamos en el bloque principal:

procedure procedimiento1(x: Integer);
Begin
  WriteLn('Parámetro recibido por valor:', x);
  x := 100;
End;

Desde el bloque principal llamamos a procedimiento1 y le enviamos el contenido de la variable valor con un 1:

var
  valor: Integer;

begin
  valor := 1;
  procedimiento1(valor);
  WriteLn('Contenido de la variable valor:', valor); //se imprime un 1

Luego que sale del procedimiento1 la variable valor sigue conservando el número 1:

En cambio el procedimiento2 recibe un parámetro Integer por referencia:

procedure procedimiento2(var x: Integer);
Begin
  WriteLn('Parámetro recibido por referencia:', x);
  x := 100;
End;

Cuando asignamos el valor 100 al parámetro por referencia x la variable que realmente se está modificando el la que le enviamos desde el bloque principal es decir "valor":

  procedimiento2(valor);
  WriteLn('Contenido de la variable valor:', valor); //se imprime un 100

Como vemos la variable "valor" fue modificada por el procedimiento2.

Un parámetro por valor hace una copia de la variable que le enviamos desde el bloque principal:

parámetro por valor

En cambio un parámetro por referencia hace que el parámetro tome la misma dirección de memoria que la variable que le pasamos (esto hace que si modificamos el parámetro se modifique la variable que le pasamos):

parámetro por referencia

Problema 2

Confeccionar un procedimiento que le enviemos por valor dos variables enteras y nos retorne mediante dos parámetros por referencia su suma y producto.
En el bloque principal solicitar la carga de los dos enteros y llamar al procedimiento, luego imprimir la suma y producto que retorna el procedimiento.

Proyecto93

program Proyecto93;

{$APPTYPE CONSOLE}

procedure SumarRestar(v1,v2: Integer; var suma, producto: Integer);
begin
  suma := v1 + v2;
  producto := v1 * v2;
end;


var
  valor1: Integer;
  valor2: Integer;
  su: Integer;
  pro: Integer;

begin
  Write('Ingrese primer valor:');
  ReadLn(valor1);
  Write('Ingrese segundo valor:');
  ReadLn(valor2);
  SumarRestar(valor1, valor2, su, pro);
  WriteLn('La suma de los dos valores es:', su);
  WriteLn('El producto de los dos valores es:', pro);
  ReadLn;
end.

El procedimiento SumarRestar consta de 4 parámetros, dos por valor y dos por referencia:

procedure SumarRestar(v1,v2: Integer; var suma, producto: Integer);

Los dos parámetros por valor (se los llama normalmente parámetros de entrada) nos sirven para poder efectuar las operaciones de suma y producto.
El tercer y cuarto parámetro son parámetros por referencia (se los llama normalmente parámetros de salida) nos sirven para que el procedimiento retorne datos, en este caso la suma y producto de los dos valores.

En el bloque principal del programa se efectúa la carga de dos enteros por teclado y se procede a llamar al procedimiento SumarRestar enviando los dos valores ingresados por teclado y otras dos variables que volverán cargadas con la suma y producto de los dos primeros parámetros:

var
  valor1: Integer;
  valor2: Integer;
  su: Integer;
  pro: Integer;

begin
  Write('Ingrese primer valor:');
  ReadLn(valor1);
  Write('Ingrese segundo valor:');
  ReadLn(valor2);
  SumarRestar(valor1, valor2, su, pro);

Una vez que finaliza el procedimiento SumarRestar podemos pasar a mostrar las variables su y pro que contienen la suma y producto de los dos valores ingresados:

  WriteLn('La suma de los dos valores es:', su);
  WriteLn('El producto de los dos valores es:', pro);

Problemas propuestos

  • Confeccionar un procedimiento que reciba por referencia dos parámetros enteros. Intercambiar el valor de los mismos dentro del procedimiento:
    procedure Intercambiar(var v1, v2: Integer);
    
    Llamar desde el bloque principal al procedimiento e imprimir las dos variables que se le pasan antes y después de ser modificadas.
  • Confeccionar un procedimiento que reciba un parámetro por referencia de tipo Integer. Incrementar en uno su valor.
    procedure Incrementar(var x: Integer);
    
    Llamar varias veces al procedimiento desde el bloque principal del programa.
Solución
program Proyecto94;

{$APPTYPE CONSOLE}

procedure Intercambiar(var v1, v2: Integer);
var
  aux: Integer;
begin
  aux := v1;
  v1 := v2;
  v2 := aux;
end;


var
  valor1: Integer;
  valor2: Integer;

begin
  valor1 := 10;
  valor2 := 20;
  WriteLn(valor1, ' ', valor2);
  Intercambiar(valor1, valor2);
  WriteLn(valor1, ' ', valor2);
  ReadLn;
end.




program Proyecto95;

{$APPTYPE CONSOLE}

procedure Incrementar(var x: Integer);
begin
  x := x + 1;
end;

var
  valor: Integer;

begin
  valor := 1;
  WriteLn(valor);
  Incrementar(valor);
  WriteLn(valor);
  Incrementar(valor);
  WriteLn(valor);
  Incrementar(valor);
  WriteLn(valor);
  Incrementar(valor);
  WriteLn(valor);
  Incrementar(valor);
  WriteLn(valor);
  ReadLn;
end.