jueves, 4 de septiembre de 2008

Módulos. Procedimientos

Módulos. Procedimientos.

Procedimientos

Un procedimiento es un módulo que presenta las siguientes partes:
  • Una cabecera
  • Un cuerpo
La cabecera presenta las siguientes partes:

  • El nombre del procedimiento
  • Una lista de parámetros, que podría estar vacía
El cuerpo del procedimiento es un bloque, dentro del cual se escriben las sentencias. Un procedimiento lo podemos ver como una caja negra –no nos interesa saber su interior- o como una caja transparente –si nos interesa saber su interior-. Para que un procedimiento pueda ser ejecutado, se deberá llamarlo o invocarlo. Los parámetros formales –aquellos que se definen en la cabecera de la función, pueden ser pasados por valor, en estos casos, se trabaja con una copia del valor pasado desde la invocación, cualquier modificación que se realice en los parámetros formales, no repercute en los parámetros actuales –los indicados en el momento de la invocación- o pueden ser pasados por referencia, también llamados por dirección o como los denomina el Lenguaje Pascal parámetros variables, en estos casos, lo que se envía no es el valor en sí, sino la dirección del objeto, por lo tanto, los parámetros actuales enviados por referencia solo pueden ser objetos que sean variables. Dentro del módulo los parámetros formales enviados por referencia contienen la dirección del parámetro actual correspondiente, cualquier valor asignado al parámetro formal, en realidad está modificando al parámetro actual. Un procedimiento se lo invoca en forma directa, debido a que es una sentencia en sí mismo, como se vió bajo el apartado sentencias simples.
Un procedimiento puede necesitar trabajar con variables internas a su ámbito, en estos casos esas variables definidas dentro del procedimiento son denominadas variables locales. Fuera del procedimiento en que han sido definidas no existen, salvo en los casos en que el procedimiento invoque a un módulo definido dentro de su ámbito, -módulos anidados- allí serán reconocidas. La comunicación entre el módulo que invocó al procedimiento y el procedimiento invocado se establece por medio de los parámetros.

Estructura de un procedimiento: -definición-




Llamada o invocación a un procedimiento

Ejemplo:

NomProc(lst_par-Actuales)


Pasaje de parámetros:

Los parámetros a un procedimiento pueden ser pasados por:
  • Valor o contenido
  • Referencia o dirección.
El pasaje de parámetros por valor o contenido, significa que lo que se está pasando es el valor del objeto enviado que puede ser un valor constante, el contenido de una variable o el resultado de una expresión; el valor recibido por el parámetro formal realiza una copia de ese valor en un área de almacenamiento temporal el Stack o Pila, eliminándose en el momento de abandonar el módulo; cualquier cambio que se produzca sobre ese objeto, el cambio se lo está realizando en la copia, por lo tanto el parámetro actual jamás se verá afectado de esas modificaciones.
En cambio el pasaje de parámetros por referencia o dirección, también llamado parámetro variable, significa que lo que se está pasando es la dirección del objeto enviado, que sólo podrá ser una variable. El parámetro formal correspondiente recibe la dirección de ese objeto y, cualquier valor que se le asigne, en realidad se lo está asignando al parámetro actual correspondiente, por lo tanto, no se trabaja con una copia sino con el propio objeto. La forma de establecer si un parámetro formal debe ser por referencia es indicando antes de la lista de parámetros la palabra reservada var. Todos aquellos parámetros que deban ser pasados por valor, entonces no se debe anteponer esa palabra.

¿Cuándo pasar parámetros por valor o por referencia?

Usamos parámetros por valor cuando conocemos previamente el valor de esos parámetros y deseamos pasarlo al módulo para que realice algún tratamiento con esos datos; aún si se cambiara su valor dentro del módulo invocado, no afecta al parámetro actual. En cambio usamos parámetros por referencia cuando el dato se va a conocer en el módulo o sabiendo su valor debemos modificarlo y se requiere saberlo en el ámbito en que fue invocado Los parámetros actuales cuando son pasados por valor pueden ser valores constantes, variables o expresiones. En cambio los parámetros actuales cuando son pasados por referencia solo pueden ser objetos variables.

Ejemplos:
Bloque principal

1: a <-- 9

2: Proc1(a,3,sqrt(a)+2.4,b)

3: Emitir(a,b)

F

4: Proc1(w,x:integer; y:real; var z:longint)


5: h <-- x + y

6: w <-- w - 2

7: x <-- x + w

8: z <-- h * x + 3

9: Emitir(h,x,z)

R

2: Parámetros actuales: los 3 primeros son pasados por valor, por lo tanto pueden ser; variables, constantes, o expresiones, en cambio el 4to. parámetro es pasado por referencia, solo puede ser un objeto variable.

4: w, x, y son parámetros formales pasados por valor, mientras que z es un parámetro formal pasado por referencia.

5: h es una variable local ¿de qué tipo, entero o real?

Prueba de escritorio

Dirección Llamada

d:231 d:1528 valores enviados valores recibidos ...var.loc..... Emite

...a......b......................... w... x...y...... z..... ..h

...9.. 87. 9, 3, 5.4, d:1528...9... 3..5.4. d:1528... 8.4 ...8.4 10 87

..................................7...10............................ 9... 87

Procedimientos definidos por el usuario:

Como ya se vió en párrafos previos, un procedimiento está formado por una cabecera que contiene el nombre del procedimiento, eventualmente una lista de parámetros y el cuerpo en donde se indican las acciones a realizar. Siguiendo estos pasos el usuario podrá definir sus propios procedimientos.

Variables globales y variables locales:

Las variables globales se definen en tiempo de compilación, reservando el espacio en el segmento de datos -un bloque de memoria cuyo tamaño máximo es de 64K bytes- la cantidad de bytes que corresponda al tipo de esa variable y ese espacio estará reservado hasta la finalización del programa, por lo tanto, estas variables son estáticas.

Las variables locales se definen en tiempo de compilación dentro del ámbito de un módulo –procedimientos o funciones-, pero no se reserva espacio hasta el momento en que el módulo es invocado, en ese instante se crean esas variables y al abandonar el módulo son eliminadas de esa región de memoria temporal. Esa región de memoria es el segmento del Stack o Pila, cuyo tamaño máximo es de 64K bytes. El valor por defecto reservado por el lenguaje Turbo Pascal es de 16384 bytes, pero puede ser ampliado o disminuido por medio de la directiva al compilador de ámbito global escribiéndola dentro del código del programa {$M Stack Size, heapmin,heapmax} o por medio de los comandos de menú del IDE Option Compiler Memory Sizes. Stack Size debe ser un valor entre 1024 y 65536 bytes y que establece el tamaño del segmento del stack, heapmin debe ser un valor en el intervalo 0 655360 bytes y heapmax debe ser un valor en el intervalo heapmin y 655360 bytes y que establece el tamaño del área del heap o montículo, región de memoria en donde se crean o eliminan las variables dinámicas en tiempo de ejecución.

Variables dinámicas:

Las variables dinámicas se definen en tiempo de ejecución por medio del procedimiento new y son eliminadas por medio del procedimiento dispose. La región de memoria en donde son creadas/eliminadas es en el heap o montículo. Debido a que la cantidad de variables globales que podemos contar en un programa no puede superar el límite de 64Kbytes, bajo estas condiciones estamos en la obligación de utilizar el heap a efectos de poder incrementar el espacio para poder contar con más variables.

Código del programa:

El código del programa que incluye al bloque principal y todos los módulos definidos en el programa se ubican en el segmento de código cuyo tamaño máximo es de 64 Kbyte. Si se necesita un mayor tamaño estamos obligados a crear unidades, cada una de las cuales no puede superar el límite de 64 Kbytes. Estas unidades estarán referenciadas en el programa en la sección uses que incorporará el código ya compilado de la unidad a nuestro programa, logrando en consecuencia romper la barrera de los 64 Kbytes para el código del programa.

De esta manera hemos visto que la memoria total estará dividida en cuatro regiones:

Segmento de Datos –Máximo 64 Kbytes, si se requiere un mayor tamaño utilizar variables dinámicas, esto es en el área del heap-.

Segmento de Código –Máximo 64 Kbytes, para ampliar el tamaño utilizar unidades c/u. con un máximo de 64 Kbytes-.

Segmento del Stack o Pila –Máximo 64 Kbytes-.

Área del heap o Montículo – resto de la memoria disponible-

Memoria convencional bajo el D.O.S. de 640Kbytes.



El siguiente cuadro muestra los objetos variables globales y los objetos variables locales o parámetros formales en el segmento del Stack –Pila- en el instante de la invocación o llamada al módulo y de su retorno. Observar sus contenidos según los casos. Si el número está precedido por d: entonces indica que es una dirección de memoria. Si el parámetro formal contiene un número precedido por d: entonces en esos casos, el parámetro ha sido pasado por referencia.

* Los parámetros o variables locales sólo existen cuando se invoca al módulo.
--- Indica que las variables globales o locales o los parámetros correspondientes de la columna no existen. 

No hay comentarios: