Contenido>Indice>Intro CursoC51

USO DE PUNTEROS Y ARRAYS EN C51



Los punteros constituyen paradójicamente uno de los puntos fuertes y a la vez puntos débiles del lenguaje C. El uso, o más apropiadamente el abuso de los punteros es la razón por la que algunos consideran peligroso al lenguaje C.

Los Punteros en Ensamblador

Para un programador en ensamblador, los punteros de C equivalen al direccionamiento indirecto que realizan las siguientes instrucciones del 8051:

MOV  R0,#40
MOV  A,@RO            ; Lectura de RAM interna 

MOV  R0,#40
MOVX A,@RO            ; Lectura de RAM externa paginada

MOVX A,@DPTR          ; Lectura de RAM externa
                        
CLR  A 
MOV  DPTR,#0040
MOVC A,@A+DPTR        ; Lectura de memoria de código

En todos los casos anteriores el dato se encuentra en una posición de memoria cuya dirección se encuentra en los registros situados a la derecha de '@'.

Los Punteros en C51

El puntero es el equivalente en C al acceso indirecto del ensamblador. Puede definirse el puntero como una variable que contiene la dirección de otra variable o constante.

Se define un puntero a unsigned char así:

unsigned char *puc;

Notar que el prefijo *, indica que el dato residente en puc es una dirección y no un valor.

En todos los ejemplos anteriores en ensamblador se utilizan dos operaciones:

  1. Poner en un registro la dirección de la variable a la que se desea acceder.
  2. Usar la instrucción apropiada para acceder indirectamente al dato.

En C se utiliza el mismo procedimiento, aunque se debe definir el puntero, mientras que en ensamblador se utilizan los registros del 8051.

/* 1 - Definir un puntero para almacenar la dirección de otra variable */

unsigned char *puc ;

/* 2 - Poner en el puntero la dirección de la variable a la que se */
     /* desea acceder indirectamente */

puc = &variable_c ;

/* 3 - Poner el dato '0xff' indirectamente en variable_c */

*puc = 0xff ;

Los pasos anteriores hacen:

  1. Reserva espacio en RAM para un  puntero. El compilador asigna un nombre simbólico a una posición de RAM, como hace con una variable normal.
  2. Carga el espacio reservado en RAM con la dirección de la variable a la que se desea acceder, equivale a 'MOV R0,#40'. La sentencia "puc = &variable_c" significa poner en puc la dirección de variable_c. En este caso el puntero se corresponde con R0 y '&' equivale al símbolo '#' utilizado en ensamblador.
  3. Mover el dato 0xff a la variable cuya dirección se encuentra en puc, lo que equivale a la instrucción  'MOV A,@R0' del ejemplo en ensamblador.

La posibilidad de asignar valores de forma directa, x = valor, o de forma indirecta, x = *y_ptr, es extremadamente útil. Veamos un ejemplo en C:

/* Demostración del uso de Punteros */

char c1;        // 1 - Define la variable c1, de tipo char
char *pc;       // 2 - Define un puntero a variable de tipo char
                       que todavía no apunta a ningún lugar
main() {
   c1 = 0xff;   // 3 - Asigna (directamente) el valor 0xff a c1 
   pc = &c1;    // 4 - Asigna a pc la dirección de c1
   *pc = 0xff;  // 5 - Asigna (indirectamente) el valor 0xff a c1
   }

 

Nota: La línea 4 hace que pc apunte a la variable c1. Una forma alternativa de hacer esto es:

/* Demostración del uso de Punteros */

char c1;        // 1 - Define la variable c1, de tipo char
char *pc = &c1; // 2 - Define un puntero a variable de tipo char
                       que apunta a la variable c1
main() {
   c1 = 0xff;   // 3 - Asigna (directamente) el valor 0xff a c1
   *pc = 0xff;  // 5 - Asigna (indirectamente) el valor 0xff a c1
   }

 

Los punteros con el prefijo *, pueden utilizarse igual que las variables normales. La sentencia:

x = y + 3 ; 

puede realizarse igualmente con punteros:

char x, y ; 
char *x_ptr = &x ; 
char *y_ptr = &y ;
*x_ptr = *y_ptr + 3 ;

o:

x = y * 25 ;
*x_ptr = *y_ptr * 25 ;

La cosa más importante a recordar con punteros es que

*ptr = var ;

significa "asignar el valor var a la variable apuntada por ptr", mientras que

ptr = &var ;

significa "asignar a ptr la dirección de la variable var". 


   Contenido>Indice>Intro CursoC51