Contenido>Indice>Intro CursoC51

ACCESO A VARIABLES EN PROGRAMAS MODULARES


Una aplicación típica, escrita en C51 puede residir en 5 módulos o ficheros fuentes. Cada fichero contendrá un número de funciones (subrutinas) que operan y utilizan variables en RAM. Cada función individualmente recibirá sus datos de entrada y devolverá sus resultados según el mecanismo de paso de parámetros establecido en C51. Además cada función utiliza variables temporales para almacenar los resultados intermedios. Cuando se programa en ensamblador, se acostumbra a reservar un lugar en memoria a cada variable (incluso las temporales), y hacerlas accesibles a todas las subrutinas.

Este método es muy ineficiente y limitaría seriamente la potencia de los programas C, debido a que la RAM interna, resultaría insuficiente para muchos programas, y además se perdería el claro mecanismo de entradas y salidas de funciones, propio de los lenguajes de alto nivel. Por otro lado, la totalidad del programa debería escribirse en un único fichero fuente, al igual que se hacía en ensamblador. El tamaño del programa resultante alargaría el proceso de compilación, y se perdería el ideal de dividir los programas en pequeños trozos fáciles de entender. Así los programas se convertirían en bloques monolíticos, cuyos listados llenarían muchísimas hojas de papel.

Por lo tanto, dentro de un programa debe existir una organización jerárquica de variables y funciones, los bloques funcionales deben identificarse y reunirse en módulos individuales, y para que ello sea posible, debe explotarse la habilidad de acceso a variables externas y a funciones de otros módulos. Lo que sigue puede ayudar a comprender: 

MODULO1.c: ********************************
   UCHAR global1 ;    (1)
   UCHAR global2 ;
   extern UCHAR ext_función(UCHAR) ;    (2)

   UCHAR int_función(UCHAR x)      (3)
   {
   unsigned int temp1  ;    (4)
   UCHAR temp2 ;
   temp1  = x * x ;
   temp2  = x + x ;
 
   x = temp1/temp2 ;
 
   return(x)    (5)
   }

/* Programa principal */
   void main(void)    (6)
   {
   UCHAR local1 ;    (4)
   UCHAR local2 ;
   local2 = int_función(local1) ;    (7)
   local1 = ext_función(local2) ;    (8)

   }
final de MODULO1.c *************************
MODULO2.c: *********************************
   extern UCHAR global1 ;    (9)

   UCHAR ext_función(UCHAR y)
   {
   UCHAR temp = 2;
   static UCHAR special ;    (10) 
   
   special++ ;
   y = temp * global1 ; 

   return(y) ;
   )

 

Línea (1): declara variables accesibles desde cualquier lugar del programa. En el caso ideal no deberían utilizarse estas variables externas o globales, pero son imprescindibles cuando una interrupción debe actualizar un valor que necesita el programa principal.

Línea (2): declara una función externa, o no definida en ese módulo. Con ello se permiten las llamadas posteriores a la función externa.

Línea (3): define una función que será llamada desde otras funciones de este módulo. La variable UCHAR x, sólo existe mientras el programa esté ejecutando esta función, y desaparecerá cuando se salga de ella. Es conveniente definir las funciones antes de que otras funciones las llamen (como hace main en este caso).

Línea (4): como sucedía antes con la variable x, estas variables locales se utilizan para guardar resultados intermedios de la función, y sólo existen mientras se ejecuta la función. Al salir de la función, el espacio que ocupaban estas variables se puede asignar a otras variables. Sin embargo las variables locales definidas en main() siempre existen, ya que todo el programa C está contenido en main().

Línea (5): permite que la función devuelva un valor a la función que la llamó. Una vez que se regrese a main(),este valor se asigna a la variable "local2".

Línea (6): define el comienzo del un programa C. Sin embargo, antes de que el programa llegue a main(), se ejecuta la rutina contenida en "STARTUP.A51", que comienza en C:0000, o posición del vector reset. La función main() no recibe ningún parámetro. 

Línea (7): llama a la función descrita arriba, y le pasa el valor "local1".

Línea (8): como en 7, solo que la función llamada reside fuera del módulo.

Línea (9): está vinculada a la Línea(1). Hace que la variable "global1" sea visible en MODULO2.C.

Línea (10): declara una variable que es local a esta función, pero que no debe ser destruida al salir. Así se comporta como una variable global, salvo que ninguna otra función puede utilizarla. Si se hubiera definido encima de la función, su accesibilidad se extendería a todas las funciones del MODULO2 que le sigan, haciéndola invisible a otros módulos.

El enlazado de los nombre de variables y funciones entre los diferentes módulos, lo realiza el linker L51. Este aspecto se trata en la Capítulo 8.


   Contenido>Indice>Intro CursoC51