Autor Tema: el tema de los punteros...  (Leído 19880 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado PalitroqueZ

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5474
    • Electrónica Didacta
el tema de los punteros...
« en: 02 de Abril de 2007, 12:20:57 »
Leyendo el documento que colgó elmasvital en este post me dieron ganas de hacer un estudio de este tema en profundidad, así aprovecho voy escribiendo y lo pego aquí por si alguien tiene problemas o desconocimiento de como usarlo.

lo que sé de punteros está en esa guía punteros en C y en Curso de C del autor Gorka Urrutia (en las sección de punteros) y mucho de lo escribiré se basará en ambos documentos.

por supuesto que estará orientado a los uC PIC y usando el PIC C Compiler de CCS.
(a ver si este compilador nos lo permite)

¿Qué es un puntero?

un puntero es una variable cuya finalidad es almacenar numeros ENTEROS POSITIVOS. Estos numeros no son numeros al azar, son direcciones de memoria que poseen el hardware específico (memoria de programa o la RAM).

¿para que pueden servir los punteros?

esta pregunta puede alborotar a mas de un programador de C, sirve para muchiiisimas cosas:

- acceso a la memoria de un hardware y/o RAM, en este caso el uC PIC.

- ahorrar memoria RAM.

- modificar mas de una variable dentro de una función (por consiguiente devolver mas de un valor)

- en arreglos y cadenas strings (arrays, matrices) juega un papel importantisimo.

- crear tablas con montones de datos (en los uC PIC que soporten acceso a la memoria de programa).

- en las computadoras se amplia el abanico de opciones.

cada paso se irá explicando paulatinamente.

¿como funcionan los punteros?

para entender el uso debido de estas variables especiales, hay que comprender bien un concepto.

cuando se crea una variable en C (llamado registro en ensamblador), el compilador reserva un espacio de memoria (programa/ram) de acuerdo al tipo de dato.

como todo en el mundo electronico - digital está basado en 2 cosas:

- el registro: es la casilla donde se almacena el dato.

- la dirección del registro: es la posición en la memoria donde está alojado el registro.

así pués tenemos 2 elementos diferentes pero que se relacionan.

conociendo la dirección del registro o variable y pudiendolo manejar nos dá un poderosa herramienta para agilizar/simplificar nuestros programas.

pero ¿como podemos acceder a la dirección de una variable?

en C se hace a través del operador & vamos con un ejemplo:

Código: C
  1. #include <18F4550.h>
  2. #use delay(clock=4000000)
  3.  
  4. void main(){
  5. int t,k;
  6.         t=5;
  7.         k= &t;
  8.         delay_cycles(1);
  9. }

al simular en el MPLAB tenemos




cuando paramos en delay_cycles(1) vemos que en k se guarda la dirección de la variable t, ¿y que guarda t? guarda el número 5. todo se realiza usando memoria RAM ó el registro de propósito general GPR

vamos a cambiar ligeramente el código, usemos 3 variables tipo entero (int)

Código: C
  1. #include <18F4550.h>
  2. #use delay(clock=4000000)
  3.  
  4. void main(){
  5. int k,l,m;
  6. int t,u,v;
  7.         t=0xfa; u=0xfb; v=0xfc;
  8.         k= &t;  l= &u;  m= &v;
  9.         delay_cycles(1);
  10. }




se repite lo mismo, el resultado de las direcciones en k, l y m son contiguas, ¿y porque digo esto?

para responder esta pregunta vamos a cambiar el código otra vez, declarando los 3 tipos de registros conocidos, int, long y float


Código: C
  1. #include <18F4550.h>
  2. #use delay(clock=4000000)
  3.  
  4. void main(){
  5. int k,l,m,n;
  6. int t;
  7. long u;
  8. float v;
  9. int z;
  10.         t=0xfa; z=0xff; u=0xfffa; v=3.45000000;
  11.         k= &t;  l= &u;  m= &v; n=&z;
  12.         delay_cycles(1);
  13. }

la simulación




observe que las direcciones de t, u , v saltan ¿porque?

dependiendo del tipo de dato se consume >= 1 byte

en el caso de t es un entero, los enteros llegan hasta 255 (1 byte)

u es un entero largo, que llega hasta 65535 (2 bytes)

v es un coma flotante, es decir, parte fraccionaria en el sistema decimal y toma 4 bytes de memoria (32 bits)

- en t tenemos una dirección que ocupa un byte [0xA]

- en u tenemos una dirección que ocupa 2 byte [0xB - 0xC]

- en v tenemos una dirección que ocupa 4 bytes [0xD - 0x10]

esto hay que tomarlo en cuenta para futuros ejemplos.

La propiedad privada es la mayor garantía de libertad.
Friedrich August von Hayek

Desconectado PalitroqueZ

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5474
    • Electrónica Didacta
Re: el tema de los punteros...
« Respuesta #1 en: 02 de Abril de 2007, 12:26:56 »
- 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

Código: C
  1. #include <18F4550.h>
  2. #use delay(clock=4000000)
  3.  
  4. //*******************************
  5. void main(){
  6. int k;      // variable normal
  7. int *p;    // la variable puntero
  8.  
  9.  k=0xfa;    // k <- 0xfa
  10.  *p=0x5;      
  11.  delay_cycles(1);
  12. }

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


Código: C
  1. #include <18F4550.h>
  2. #use delay(clock=4000000)
  3.  
  4. //*******************************
  5. void main(){
  6. int k;      // variable normal
  7. int *p;    // la variable puntero
  8.  p=&k;     // dirección de k copiada a p
  9.  k=0xfa;    // k <- 0xfa
  10.  *p=0x5;      // k <- 0x5
  11.  delay_cycles(1);
  12. }

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

Código: C
  1. #include <18F4550.h>
  2. #use delay(clock=4000000)
  3.  
  4. //*******************************
  5. void main(){
  6. int i;      // variable normal
  7. int *p;    // la variable puntero
  8. int j;
  9. int *q;
  10. int k;
  11.  
  12.  p=&i;     // dirección de i copiada a p
  13.  q=&j;
  14.  
  15.  i=0xfa;    // i <- 0xfa
  16.  j=0x11;
  17.  k=0x22;
  18.  
  19.  *p=0x5;      // i <- 0x5
  20.  *q=0x33;
  21.  
  22.  delay_cycles(1);
  23. }




- 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 byte


modificando el código para que i sea del tipo float

Código: C
  1. #include <18F4550.h>
  2. #use delay(clock=4000000)
  3.  
  4. //*******************************
  5. void main(){
  6. float i;      // variable normal
  7. float *p;    // la variable puntero
  8.  
  9. long j;
  10. long *q;
  11. int k;
  12.  
  13.  i=2.51;    // i <- 0xfa
  14.  j=0x11;
  15.  k=0x22;
  16.  
  17.  p=&i;     // dirección de i copiada a p
  18.  q=&j;
  19.  
  20.  *p=3.99;      // i <- 0x5
  21.  *q=0x33;
  22.  
  23.  delay_cycles(1);
  24. }




- 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)

Código: C
  1. #include <18F4550.h>
  2. #use delay(clock=4000000)
  3.  
  4. //*******************************
  5. void main(){
  6. float i;      // variable normal
  7. int *p;    // la variable puntero
  8. long j;
  9. long *q;
  10. int k;
  11.  
  12.  i=2.51;    // i <- 0xfa
  13.  j=0x11;
  14.  k=0x22;
  15.  
  16.  p=&i;     // dirección de i copiada a p
  17.  q=&j;
  18.  
  19.  *p=3.99;      // i <- 0x5
  20.  *q=0x33;
  21.  delay_cycles(1);
  22. }




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

Código: C
  1. #include <18F4550.h>
  2. #use delay(clock=4000000)
  3.  
  4. //*******************************
  5. void main(){
  6. float i;      // variable normal
  7. float *p;    // la variable puntero
  8. long j;
  9. long *q;
  10. int k;
  11.  
  12.  i=2.51;    // i <- 0xfa
  13.  j=0x11;
  14.  k=0x22;
  15.  
  16.  p=&i;     // dirección de i copiada a p
  17.  q=&j;
  18.  
  19.  *p=3.99;      // i <- 0x5
  20.  *q=0x33;
  21.  delay_cycles(1);
  22. }




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.

« Última modificación: 02 de Abril de 2007, 12:30:03 por PalitroqueZ »
La propiedad privada es la mayor garantía de libertad.
Friedrich August von Hayek

Desconectado reiniertl

  • Moderadores
  • PIC24H
  • *****
  • Mensajes: 1187
Re: el tema de los punteros...
« Respuesta #2 en: 02 de Abril de 2007, 12:40:55 »
¡Que bárbaro!

Te exhorto a que sigas haciendo este trabajo, que te está quedando muy bueno, siempre he querido hacerlo pero nunca he tenido la oportunidad por falta de tiempo y un poco de voluntad, pero a usted le está quedando como para chuparse los dedos.

Realmente me parece que voy a aprender mucho con este cursillo sobre punteros en C y con PIC. La razón: no es lo mismo punteros sobre una PC que en una máquina como los PIC, los PIC imponen limitaciones y ciertos cambios al concepto, pero aún así son herramientas de mucho poder y a mi me gusta mucho utilizarlos.

Un saludo Reinier
« Última modificación: 02 de Abril de 2007, 12:43:00 por reiniertl »

Desconectado PalitroqueZ

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5474
    • Electrónica Didacta
Re: el tema de los punteros...
« Respuesta #3 en: 04 de Abril de 2007, 11:09:11 »
analizando nuevamente lo hablado referente al size de los punteros en CCS, y en un intento de explicar que el tipo de dato y el tamaño del apuntado son 2 cosas distintas, vamos hacer un ejemplo donde se verá claramente:

para ello vamos a usar una directiva llamada #locate

en ayuda del compilador reza asi:

#LOCATE works like #BYTE however in addition it prevents C from using the area

bueno esto quiere decir que mi variable normal la puedo alojar en la dirección de la ram que yo quiera (dentro de limites)

algo así como si en ensamblador fuera

variable_normal EQU 0xNNNN

esto nos va a servir porque sería como manipular el contenido de un puntero pero en tiempo de diseño

Código: C
  1. #include <18F4550.h>
  2. #use delay(clock=4000000)
  3. //*********************************
  4.  
  5.  int dato=0xaa;    // declaramos dato (GPR) y lo cargamos con 0xAA
  6.  #locate dato = 0xff  // le decimos al compilador que dato estará en la dirección 0xFF                  del área de registro de propósito general, traducido, en la RAM del PIC
  7.  
  8. void main(){
  9. int *p;  // declaramos un puntero como entero (igual que dato)
  10. int t;   // otra variable normal
  11.  
  12.  p=&dato;  // inicializamos al puntero
  13.  
  14.  *p=0xbb;  // dato <- 0xBB
  15.  
  16.  delay_cycles(1);  // un nop
  17. }












fijense que el puntero p ocupa 2 bytes a pesar que está declarado como int (1 byte). ¿ven como es?

vamos a modificar este ejemplo pero usando float (4 bytes) y colocando el GPR en la dirección 0xAF








noten que el puntero p se mantuvo en 2 bytes siendo éste declarado como float

aquí podemos seguir inventando y crearnos situaciones dificiles que nos compliquen la vida, como por ejemplo, tratar de desbordar al puntero, o bajarle el size <= 1 byte y ver que sucede.

ya que quiero seguir inventando jeje, propongo una situación extrema, para el 18F4550, tenemos una memoria de datos que llega hasta 0x7FF (pag 66 39632D.pdf)

para que funcione 0x7FF debe ser el 4 byte para un float, entonces


float dato=1.23456789;
#locate dato = 0x7FB
...




si funcionó

que pasa si asignamos el dato a 0x800




allí vemos que el puntero se cargó bien, pero el MPLAB-SIM nos mandó a freir monos con el dato, ¿porque?

a partir de allí no hay memoria de datos y las direcciones se deberian leer como puros 0x0 a pesar que compiló bien, aquí también hay que estar pendiente con el direccionamiento (en programas de computadoras pueden ocurrir cuelgues)

La propiedad privada es la mayor garantía de libertad.
Friedrich August von Hayek

Desconectado PalitroqueZ

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5474
    • Electrónica Didacta
Re: el tema de los punteros...
« Respuesta #4 en: 04 de Abril de 2007, 11:13:12 »
- punteros en funciones:

todo lo que hagamos en C se hace a través de funciones o procedimientos, desde el punto de vista matemático una función se define así (viene de este link ):

Citar
cita:

Una función es una relación entre dos variables numéricas, habitualmente las denominamos x e y; a una de ellas la llamamos variable dependiente pues depende de los valores de la otra para su valor, suele ser la y; a la otra por tanto se la denomina variable independiente y suele ser la x.

Pero además, para que una relación sea función, a cada valor de la variable independiente le corresponde uno o ningún valor de la variable dependiente, no le pueden corresponder dos o más valores.



aplicandolo a la programación, significa que podemos tener varios argumentos o parametros de entrada, pero solo tendremos un dato de salida y eso no es todo, en C una función pasa los argumentos por valor.

¿que quiere decir esto?

que cuando llamemos a la función y le pasemos el dato como argumento, ésta copiará ese dato en su propia función sin alterar la variable original. veamos un ejemplo:


Código: C
  1. #include <18F4550.h>
  2. #use delay(clock=4000000)
  3. //*********************************
  4. int mi_funcion(int argumento1, argumento2){
  5.         delay_cycles(1);
  6. return (argumento1 + argumento2);
  7. }
  8.  
  9. //*******************************
  10. void main(){
  11. int k,l,resultado;
  12. k=5; L=2;
  13.         resultado = mi_funcion(k,L);
  14.         delay_cycles(1);
  15. }







fijense que cuando llamo a mi_funcion, se copia el contenido de k -> argumento1 y L -> argumento2 , luego hace la suma y regresa un dato con el resultado de la suma.

k y L se quedan con el mismo valor anterior.

¿y si queremos cambiar esas variables como se hace?

bueno seguro que alguien llegará y colocará a k y L como globales y entonces así se puede modificar en cualquier lado.

pero si la variable es local, dentro de main, no se puede modificar fuera de main...
a menos que usemos punteros. -aja- ¿y como se haría eso?

se haría pasando el argumento a la función como referencia, haciendo referencia a la dirección, es decir lo que le voy a pasar a la función es la dirección de k, L  entonces allí si se puede modificar a gusto. un ejemplo:


Código: C
  1. #include <18F4550.h>
  2. #use delay(clock=4000000)
  3.  
  4. //*********************************
  5. int mi_funcion(int argumento1, argumento2, *la_k, *la_L){
  6.         delay_cycles(1);
  7.         *la_k=0xFF; *la_L=0xAF;
  8. return (argumento1 + argumento2);
  9. }
  10.  
  11. //*******************************
  12. void main(){
  13. int k,l,resultado;
  14. k=5; l=2;
  15.         resultado = mi_funcion(k,l,&k,&l);
  16.         delay_cycles(1);
  17. }

para ver con claridad ese código, un videito simulando en MPLAB:

simulacion paso a paso


La propiedad privada es la mayor garantía de libertad.
Friedrich August von Hayek

Desconectado RiBerZerO

  • PIC12
  • **
  • Mensajes: 52
Re: el tema de los punteros...
« Respuesta #5 en: 04 de Abril de 2007, 23:01:25 »
Solo quiero dar mi mas sincero agradecimiento con esto me haces recordar muchas cosas que ya no ocupaba de mis clases de C jeje olvidemos las variables globales y a programar como los PIC mandan jeje con programacion de elite  :D

Vas por el mejor camino y lo sabes sigue asi :-/
No SUEÑES tu vida, VIVE tu sueño

Desconectado maunix

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 4751
    • Mi Sitio Web Personal
Re: el tema de los punteros...
« Respuesta #6 en: 05 de Abril de 2007, 10:37:56 »
Yo opino que el uso de variables globales NO es un pecado.  En los microcontroladores es más necesario que en una pc.

Es más, hasta es ACONSEJABLE usarlas para evitar el uso excesivo del stack que en muchas aplicaciones es inaceptable por las demoras que conlleva.

Saludos
- La soberbia de un Einstein es entendible.. la de un salame es intolerable (A.Dolina)
- En teoría no hay diferencia entre la teoría y la práctica. En la práctica... si la hay.
- Lee, Lee, Lee y luego pregunta.(maunix)
- Las que conducen y arrastran al mundo no son las máquinas, sino las ideas (V. Hugo)
- Todos los hombres se parecen por sus palabras; solamente las obras evidencian que no son iguales.(Moliere)
- Todo debería ser hecho tan simple como sea posible pero no mas simple que eso.(A.Einstein)

Desconectado RiBerZerO

  • PIC12
  • **
  • Mensajes: 52
Re: el tema de los punteros...
« Respuesta #7 en: 06 de Abril de 2007, 02:27:27 »
Yo creo que como todos los metodos de programacion las variables globales y los apuntadores tienen un uso especifico, su utilidad depende mucho de la aplicacion que se este utilizando, es cierto no es un pecado. es un modo de programacion  :-)

Yo creo que comparar esto es como querer decir que es mejor un FOR( ; ; ) que un WHILE.  :lol:

Mientras una variable global nos da acceso a ella en todo el programa  solo llamandola por su nombre, un apuntador nos manda la direccion para que sea modificada solo desde una funcion llamada directamente de la funciona a la que pertenece esta variable. Por lo cual no puede ser modificada por funciones ajenas al flujo.

El uso de un apuntador nos ayudara a muchas cosas por ejemplo en aplicaciones en las cuales se quiera guardar algun archivo en forma de nodo y asi despues aumentar el tamaño claro esto usando extructuras. Tambien se puede utilizar para tener acceso a variables definidas en una funcion a las cuales queramos tener acceso. Tambien nos ofrece la posibilidad de manejar matrices redimencionables.

Muchas veces tambien los apuntadores se utilizan para seguridad, ya que una variable global pude ser llamada desde cualquier parte del programa, por lo cual no son recomendables para programas donde se guarden claves o algo parecido.

Bueno este es mi muy personal punto de vista se aceptan criticas para tener mejor angulo de vision.

Algo que no entiendo

Citar
para evitar el uso excesivo del stack

Como puede un apuntador el cual utilizas para que una funcion pase la direccion de memoria de una variable ya definida y una funcion a la cual tienes que llamar (por lo cual ya gastaste stack) gastar mas stack, creo que te refieres a gastar mas RAM, con la variable de 2 bytes que utilizas para guardar el apuntador, pero hasta donde yo se (que no es mucho) el stack solo se gasta al hacer un llamado a funcion por lo cual se genera un salto y en el stack se guarda la direccion del en la cual se encuentra en contador de programa antes realizar el salto y asi poder regresar. Por lo cual yo creo que el stack solo se puede gastar excesivamente si se realizan muchos llamados a funciones seguidos, es decir que llames a una funcion y luego cuando estes en esa funcion llames a otra y otra y asi sucecivamente.

Bueno ese es mi punto de vista que puede tal vez estar equivocado

Gracias por el tiempo y disculpen las molestias :-/
No SUEÑES tu vida, VIVE tu sueño

Desconectado reiniertl

  • Moderadores
  • PIC24H
  • *****
  • Mensajes: 1187
Re: el tema de los punteros...
« Respuesta #8 en: 06 de Abril de 2007, 13:01:55 »
Yo concuerdo en parte con Maunix y en parte con RiBerZerO, pero no del todo con ninguno de los dos

Por ejemplo los microprocesadores de la linea INTEL, dentro de los que caen los uC 8051 y algunos de sus parientes el STACK se utiliza no solo para guardar las direcciones que en algún momento se utilizarán para retornar de una llamada a subrutina o interrupción, también se puede guardar el contexto del programa antes del salto o inmediatemente después de entrar a una ISR, para ello están las instrucciónes POP y PUSH, en muchos procesadores. En los PIC, por lo menos en los que conozco, no hay POP y PUSH para todo tipo de registros y en las familias de gama media no se puede tener acceso al STACK, en los 18 tenemos acceso de lectura pero no podemos controlarla.

El uso de apuntadores es una herramienta poderosa, siempre que se sepa donde y para qué utilizarlos, por ejemplo pasar variables muy grandes (un arreglo, estructura o unión) con varios bytes puede costar más en RAM y pila que pasar un puntero con la dirección donde está esa estructura, ya que el compilador para pasar el dato tiene que hacer una copia en memoria, mientras que con el puntero solo reserva memoria para el apuntador que generalmente tienen tamaño fijo, acorde con el espacio de memoria que se puede direccionar en el sistema.

El uso de variables globales también es válido, y en la programación de uC y en todos los tipos de programación se utiliza habitualmente, pero los punteros no se crearon por gusto, ellos tienen su campo de aplicación y la programación con uC se puede ver muy beneficiada con ellos, por ejemplo tenemos muchas funciones como strcpy que utilizan apuntadores y nosotros mismos al declarar char MiVariable[10] estamos creando un aputador especial al tipo de datos char. Hay lenguajes que tratan de ocultar al programador el uso de aputadores los programadores en C son bastante críticos en cuanto a eso, por ejemplo tenemos a BASIC y PASCAL, donde el uso de apuntadores es pobre o simplemente no existe la posibilidad de utilizarlos aunque el compilador si utilice estas técnicas al compilar el código.

Esa es mi modesta opinión que también puede estar un poco equivocada.

De todos modos estos posts de PalitroqueZ me parecen muy buenos y esclarecedores.

Un saludo Reinier

Desconectado maunix

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 4751
    • Mi Sitio Web Personal
Re: el tema de los punteros...
« Respuesta #9 en: 06 de Abril de 2007, 14:11:57 »
RiberZer0 y reintertl, ¡creo que han hecho mas extensivo mi comentario de lo que realmente fué!

Simplemente dije que el uso de variables globales no es ningún pecado! pero por supuesto depende del caso.

Cito un ejemplo, si usamos una variable local en cada subrutina que tenemos y dichas subrutinas no se llaman en simultáneo, entonces es ideal (pensando en velocidad y espacio de código) el usar una variable global, estática y en la access ram (si tenemos un 18F o un 16F de los grandes).

En ese caso, no hay acceso al stack para la creación de la variable, manipulación y posterior liberación!!  Ni hablar si usamos bancos contiguos para el stack y debe el compilador manejar el FSRnH y FSRnL

Por supuesto si tenemos arreglos de datos, el uso de punteros se hace fundamental e imprescindible para ahorrar código y velocidad, pero eso no es de lo que yo estaba hablando.

El uso de variables locales aumenta la legibilidad y la portabilidad pero también reduce la velocidad y aumenta el tamaño del código y eso hay que tenerlo muy en cuenta al trabajar con microcontroladores.

Saludos y espero haber aclarado el punto.

- La soberbia de un Einstein es entendible.. la de un salame es intolerable (A.Dolina)
- En teoría no hay diferencia entre la teoría y la práctica. En la práctica... si la hay.
- Lee, Lee, Lee y luego pregunta.(maunix)
- Las que conducen y arrastran al mundo no son las máquinas, sino las ideas (V. Hugo)
- Todos los hombres se parecen por sus palabras; solamente las obras evidencian que no son iguales.(Moliere)
- Todo debería ser hecho tan simple como sea posible pero no mas simple que eso.(A.Einstein)

Desconectado RiBerZerO

  • PIC12
  • **
  • Mensajes: 52
Re: el tema de los punteros...
« Respuesta #10 en: 06 de Abril de 2007, 18:03:23 »
Bueno lo de los apuntadores y variables globales esta claro se utilizan cuando hacen falta  :D lo que todavia no entiendo bien y me gustaria que me esplicaran, es que tiene que ver la creacion de una variable con el uso del stack, al menos yo no habia encontrado una relacion, por lo cual pido por favor que me expliquen :?

Bueno ya he corrido un programa y en la simulacion el hardware stack solo usa 2 localidades independientemente de si utilizo apuntadores y variables globales para el paso de los parametros.

Por su explicacion muchas gracias nos vemos luego :-/
No SUEÑES tu vida, VIVE tu sueño

Desconectado maunix

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 4751
    • Mi Sitio Web Personal
Re: el tema de los punteros...
« Respuesta #11 en: 06 de Abril de 2007, 21:23:43 »
Bueno lo de los apuntadores y variables globales esta claro se utilizan cuando hacen falta  :D lo que todavia no entiendo bien y me gustaria que me esplicaran, es que tiene que ver la creacion de una variable con el uso del stack, al menos yo no habia encontrado una relacion, por lo cual pido por favor que me expliquen :?

El uso del stack (del compilador) está directamente relacionado al paso de parámetros y al uso de variables "locales" a una función.   Si usas una variable local, casi seguro que se crea en el stack (esto lo puedo afirmar en el caso del C18 que lo conozco bien) , pero pudiera ser que algún modo de optimización evite esto en ciertos casos en que la función sea llamada por ejemplo una sola vez.

Ahora bien, las razones son simples.  Las variables locales , como tales, "viven" durante la función y no fuera de ella.  Por ello se crean y destruyen  en la función, de ahí el que estén en el stack.  Llegado el caso es como un parámetro.

Espero se haya entendido.

PD: asumo que sabes lo que es el stack de variables del compilador.  Si lo desconoces por favor pregunta de nuevo. 
- La soberbia de un Einstein es entendible.. la de un salame es intolerable (A.Dolina)
- En teoría no hay diferencia entre la teoría y la práctica. En la práctica... si la hay.
- Lee, Lee, Lee y luego pregunta.(maunix)
- Las que conducen y arrastran al mundo no son las máquinas, sino las ideas (V. Hugo)
- Todos los hombres se parecen por sus palabras; solamente las obras evidencian que no son iguales.(Moliere)
- Todo debería ser hecho tan simple como sea posible pero no mas simple que eso.(A.Einstein)

Desconectado RiBerZerO

  • PIC12
  • **
  • Mensajes: 52
Re: el tema de los punteros...
« Respuesta #12 en: 07 de Abril de 2007, 01:56:20 »
Bueno la verdad yo pense que estabamos hablando del hardware stack del micro, lo de las variables locales lo sabia pero no de su almacenamiento en un stack, sobretodo a nivel compilador por lo cual agradeceria una pequeña explicacion gracias
No SUEÑES tu vida, VIVE tu sueño

Desconectado Nocturno

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 18286
    • MicroPIC
Re: el tema de los punteros...
« Respuesta #13 en: 07 de Abril de 2007, 02:35:02 »
Gracias por tu esfuerzo Palitroquez. Me ha encantado leer tus artículos sobre punteros con tantísimo nivel de detalles y gráficos.

Desconectado Cryn

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 4169
Re: el tema de los punteros...
« Respuesta #14 en: 08 de Abril de 2007, 14:23:37 »
tengo esta funcion:

Código: [Seleccionar]
int32 entero(int dato[])   // funcion para convertir el array en entero
{
   int32 num=0;         // inicialización del número convertido
   cont=10000;         // valor inicial para el multiplicador
   dig=0;         // inicialización de dígtos
   do            // bucle de conversión
   {
      num=num+dato[dig]*cont;   // obtención del primer número del array (decenas de mil)
      cont=cont/10;      // se reduce orden de magnitud del miltiplicador
      dig++;         // incrementa el valor de la posición del array
   }while(dig!=5);      // se realiza mientras no se llegue al final del array
   return num;         // retorna el valor convertido
}

y el main tengo:
      num1=entero(dato1);   // lo convierte a entero

y defini antes: int dato1[5];

y este dato1 tiene 5 valores distintos cada vez, en un orden y lo quiero convertir a entero, osea digamos tengo {0,0,0,4,5}
lo convertira a un int=45 (la funcion hace la labor de no tomar en cuenta los ceros)

bueno lo hice de esa forma y funciona correctamente, ahora quiero usar punteros (para que el programa sea mas efectivo) y nose como hacerlo, me dan una ayudita?
.