- probando punteros.siempre que se declare una variable puntero, al momento de usarlo se debe especificar la dirección de apuntamiento de la variable normal, porque entonces no se puede guardar un dato sino sabemos donde lo vamos a guardar. (obvio ¿verdad?)
quiere decir que se le debe pasar el número por valor de la dirección de la variable normal.
nota:
- pasar un dato por valor: se copia el dato de una variable a otra.
- pasar un dato por referencia: se mueve/modifica el dato en la misma variable.
- variable normal: la variable que normalmente usamos.
- variable puntero: es la variable especial que estamos estudiando.
un ejemplo sencillo usando punteros, tenemos
#include <18F4550.h>
#use delay(clock=4000000)
//*******************************
void main(){
int k; // variable normal
int *p; // la variable puntero
k=0xfa; // k <- 0xfa
*p=0x5;
delay_cycles(1);
}
dentro del código reconocemos de inmediato quien es el puntero: el que tiene el simbolo * debe ir antes de la letra p y sin separación
*p
asi es como se debe declarar.
si nos vamos a MPLAB-SIM, y trazando hasta delay_cycles(1) vemos en la ventana LOCAL:
pero -¡no aparece nada en p!- ¿porque?
es simple: porque no fijamos una dirección que apuntara p, y esto es muy importante saberlo, era lo que se decía al inicio de este post. vamos a darle la dirección de k
#include <18F4550.h>
#use delay(clock=4000000)
//*******************************
void main(){
int k; // variable normal
int *p; // la variable puntero
p=&k; // dirección de k copiada a p
k=0xfa; // k <- 0xfa
*p=0x5; // k <- 0x5
delay_cycles(1);
}
el resultado:
ahora si funciona OK nuestro código. si ven la línea:
p=&k;
noten que se usa el puntero sin el * significa que voy a guardar allí una dirección y el compilador lo interpreta de esa manera.
y con esta línea:
*p=0x5;
estoy modificando el contenido de k, (indirectamente)
otro detalle a tomar en cuenta es que para apuntar cierto tipos de datos, se debe declarar al apuntador con el mismo tipo de datos.
int k; // si queremos apuntar a k
int *p; // p debe ser tipo int
char c; // si queremos apuntar a c
char *p // p debe ser tipo char
no estoy queriendo decir que el tipo de datos que contendrá el puntero sea de ese tipo de datos, el puntero siempre soportará numeros enteros positivos, en realidad esto ya es a nivel interno del compilador.
para entender el enredo que acabo de escribir vamos a hacer un ejemplo:
en este código voy a escribir 2 punteros y 3 variables normales
#include <18F4550.h>
#use delay(clock=4000000)
//*******************************
void main(){
int i; // variable normal
int *p; // la variable puntero
int j;
int *q;
int k;
p=&i; // dirección de i copiada a p
q=&j;
i=0xfa; // i <- 0xfa
j=0x11;
k=0x22;
*p=0x5; // i <- 0x5
*q=0x33;
delay_cycles(1);
}
- entre i, p hay 1 byte -> i ocupa 1 byte.
-
entre p, j hay 2 byte -> puntero p ocupa 2 byte- entre j, q hay 1 byte -> j ocupa 1 byte
-
entre q, k hay 2 byte -> puntero q ocupa 2 bytemodificando el código para que i sea del tipo float
#include <18F4550.h>
#use delay(clock=4000000)
//*******************************
void main(){
float i; // variable normal
float *p; // la variable puntero
long j;
long *q;
int k;
i=2.51; // i <- 0xfa
j=0x11;
k=0x22;
p=&i; // dirección de i copiada a p
q=&j;
*p=3.99; // i <- 0x5
*q=0x33;
delay_cycles(1);
}
- entre i, p hay 4 byte -> i ocupa 4 byte.
-
entre p, j hay 2 byte -> puntero p ocupa 2 byte- entre j, q hay 2 byte -> j ocupa 2 byte
-
entre q, k hay 2 byte -> puntero q ocupa 2 byte en ambos casos a pesar que cambiamos el tipo de declaración de los punteros, se mantienen en 2 bytes, eso quiere decir que para el compilador el tamaño de un puntero es de 2 bytes, ojo no confundir con el tipo de datos a direccionar, eso es otra cosa.
PalitroqueZ ¡sigo sin entender!
vamos con otro ejemplo:
supongamos que i sea del tipo float (4 bytes) pero su apuntador lo declaramos como int (1 byte)
#include <18F4550.h>
#use delay(clock=4000000)
//*******************************
void main(){
float i; // variable normal
int *p; // la variable puntero
long j;
long *q;
int k;
i=2.51; // i <- 0xfa
j=0x11;
k=0x22;
p=&i; // dirección de i copiada a p
q=&j;
*p=3.99; // i <- 0x5
*q=0x33;
delay_cycles(1);
}
noten que el nuevo valor de i no corresponde con el valor que indirectamente le dimos con el apuntador. ¿porque?
porque declaramos a ese apuntador como entero (int) y con ello le estamos diciendo al compilador que reserve para p 1 byte de dirección en vez de 4 bytes que son los que se necesitan y por eso ocurre ese truncamiento y dá ese valor extraño.
para corregir esto, se declara a p del MISMO tipo de dato de i
#include <18F4550.h>
#use delay(clock=4000000)
//*******************************
void main(){
float i; // variable normal
float *p; // la variable puntero
long j;
long *q;
int k;
i=2.51; // i <- 0xfa
j=0x11;
k=0x22;
p=&i; // dirección de i copiada a p
q=&j;
*p=3.99; // i <- 0x5
*q=0x33;
delay_cycles(1);
}
aquí se lee que está correcto el resultado, hay que estar pendiente con ese detalle.
nota: lo que he investigado hasta ahora, los punteros tiene un máximo de 2 bytes para almacenar direcciones y al parecer el CCS sigue la misma normativa.
si buscan en la ayuda veran que hay una directiva llamada #device xxxxx
con 4 modos de selección:
CCS2,CCS3,CC4 y ANSI
con CCS2 y CCS3 el tamaño (size) del puntero es de 1 byte en partes de 14, 16 bits
y con CCS4 (modo por defecto) el size es de 2 bytes
(comprobado en el MPLAB-SIM)
no se preocupen por esta última parte, como ya mencioné anteriormente esto lo realiza el compilador internamente, nosotros por lo que debemos preocuparnos es por el tipo de datos a declarar.