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

0 Usuarios y 2 Visitantes están viendo este tema.

Desconectado PalitroqueZ

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5474
    • Electrónica Didacta
Re: el tema de los punteros...
« Respuesta #15 en: 09 de Abril de 2007, 17:08:17 »
Hola amig@s ya estoy de vuelta y leo varios mensajes  :)

que buen debate hay, yo les tengo que decir que sé muy poco sobre el tema del stack manejado en forma de parametros, como lo plantea Mauricio. no se si será mejor o peor, ya la experiencia me lo dirá. y sus opiniones deben ser tomadas muy en cuenta por la gran experiencia que poseen.

en base a esa pregunta que haces Cryn es parte del siguiente estudio, pero me atrevo a decirte que en lenguaje C no se pasa un array como argumento, y por eso el uso de puntero es un buen ejemplo de aplicación, en tu código lo que debes hacer es pasar la dirección del primer dato como parámetro (usando el operador & )y luego dentro del código haces el llamado de los demas datos (ya sea usando el operador * ó por medio de subindices)

parámetro= argumento

continuamos ....


-Punteros en Arrays

como sabran los arrays son arreglos de datos que van en direcciones consecutivas, es decir, uno detras del otro. un ejemplo de ello:

char cadena[7]={'T','o','d','o','P','i','c'};

probandolo en un código:

Código: C
  1. #include <18F4550.h>
  2. #use delay(clock=4000000)
  3. //*********************************
  4. char cadena[7]={'T','o','d','o','P','i','c'};
  5.  
  6. void main(){
  7. char c;
  8. int t;
  9.  
  10. for(t=0;t<7;t++){
  11.  c=cadena[t];
  12. }
  13.  delay_cycles(1);
  14. }








se puede usar punteros en el ejemplo anterior ¿como?

- declarando un puntero como char:

 char c, *p;

- lo inicializamos (le damos la dirección del primer elemento del array:

  p=&cadena[0];

- luego hacemos un barrido de direcciones para tomar el contenido de cada elemento y guardarlo en c

for(t=0;t<7;t++){
 c= *p + t;
}

ese programa tiene 2 errores y ya de una les digo que no funcionará:

- el primer error:

  según la precedencia del operador primero está el puntero y luego viene la suma, y así estariamos sumando direcciones que varian, la solución es usar *(p+i)

¿y que es eso de que varian?

cuando se recorre el arrays con el puntero, este debe ir sumando direcciones, pero direcciones de numeros constantes, es decir, si el tipo de datos es 1 byte, entonces el puntero debe acumular numeros enteros de 1 byte en 1 byte

si el tipo de datos es long (entero largo) entonces el puntero debe ir sumando direcciones de 2 bytes en 2 bytes

¿porque digo esto? es que p quedará fijo (la dirección) y el truco está en desplazar al puntero tantas posiciones sea el size del tipo de dato

este sería el segundo error y la solución es la misma *(p+i)

vamos a cambiar ese ejemplo por numeros long para que se entienda

Código: C
  1. #include <18F4550.h>
  2. #use delay(clock=4000000)
  3. //*********************************
  4. long cadena[7]={1000,2000,3000,4000,5000,6000,7000};
  5.  
  6. void main(){
  7. long c, *p;
  8. int t;
  9.  
  10.  p=&cadena[0];
  11.  
  12.  for(t=0;t<7;t++){
  13.   c= *p + t;
  14.  }
  15.  delay_cycles(1);
  16. }










fijense que p queda inmutable, y lo que hace el programa es contenido[0] + t

¡grave error!

arreglando el programa con *(p+t)








con esto estamos garantizando que el puntero se moverá de 2 bytes en 2 bytes, es decir

*(p+t) =

 0x5 + 0x2 (desplazamiento de 2 byte)-> dame el contenido de la dirección 0x5
 0x5 + 1x2          "                -> dame el contenido de la dirección 0x7
 0x5 + 2x2          "                -> dame el contenido de la dirección 0x9
 0x5 + 3x2          "                -> dame el contenido de la dirección 0xA
 ...

  noten que la suma se realiza no intervalos de t sino en intervalos del ancho del tipo de dato.
  
una pregunta ¿y esto no es lo mismo que se hizo en el código del inicio del post?

o sea que ¿ c = cadena[t]; es igual a c = *(p + t) cuando p = &cadena[0]; ?

pues si señores y señoras, acabamos de ver un array al desnudo, como funciona en realidad, no es mas que un vulgar puntero escondido a nuestra vista.

solo que para hacer fácil la programación el compilador lo acepta de esta manera

si p es un puntero -> p = cadena (para el primer indice del arreglo)

es totalmente válido, se acepta que cadena es un puntero constante, o como le diría yo: un puntero nulo (ya que no se ve y tampoco se puede modificar)

ejemplos validos:

cadena[0]  =   *cadena

cadena[2]  = *(cadena + 2)

cadena  = *(cadena + i)


nota:
- el operador () es el primero que atiende el compilador antes que al resto

- cuando vayamos a matrices (arrays multidimensionales) vamos a ver con claridad el recorrido de un puntero

acomodando el código original, el que tenía la cadena de caracteres:

Código: C
  1. #include <18F4550.h>
  2. #use delay(clock=4000000)
  3. //*********************************
  4. char cadena[7]={'T','o','d','o','P','i','c'};
  5.  
  6. void main(){
  7. char c, *p;
  8. int t;
  9.  
  10.  p=cadena;
  11.  
  12. for(t=0;t<7;t++){
  13.   c=*(p+t);
  14.  }
  15.  delay_cycles(1);
  16. }








Nota Errata: los ejemplos de programas de este post, donde sale ...p+i... en realidad quise decir ...p+t... la variable i no existe en los ejemplos de este post

« Última modificación: 10 de Septiembre de 2009, 12:24:17 por PalitroqueZ »
La propiedad privada es la mayor garantía de libertad.
Friedrich August von Hayek

Desconectado Cryn

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 4169
Re: el tema de los punteros...
« Respuesta #16 en: 10 de Abril de 2007, 02:03:17 »
ahhh ok, ahora mismo lo reviso

te comentare, gracias.
.

Desconectado gauchosuizo

  • Colaborador
  • PIC18
  • *****
  • Mensajes: 457
Re: el tema de los punteros...
« Respuesta #17 en: 10 de Abril de 2007, 10:36:29 »
hola

muy bueno PalitroqueZ, segui asi, que vamos a aprender un monton.
Saludos desde Suiza, Pablo.

Desconectado jfh900

  • Moderadores
  • DsPIC30
  • *****
  • Mensajes: 3595
Re: el tema de los punteros...
« Respuesta #18 en: 10 de Octubre de 2007, 08:58:56 »
Una pregunta referente a los tipos de variables. ¿Las variables locales en los pic de la gama alta se crean en el stack?.

Un saludo.
* Cuando hables, procura que tus palabras sean mejores que el silencio.
* 'Todos somos ignorantes, lo que ocurre es que no todos ignoramos las mismas cosas.' Albert Einstein.
* No hay nada peor que un experto para evitar el progreso en un campo
* "La vida es como una novela. No importa que sea larga, sino que esté bien narrada" Seneca
* La vida no se vive por las veces que respiras, sino por los momentos que dejan sin aliento.
* Dios dijo: ∇·E=ρ/ε0 ; ∇·B=0 ; ∇xE=-dB/dt ; ∇xB= μ0ε0dE/dt..y la luz se hizo..!!..

Desde España Jesús

Desconectado maunix

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 4751
    • Mi Sitio Web Personal
Re: el tema de los punteros...
« Respuesta #19 en: 10 de Octubre de 2007, 11:00:38 »
Una pregunta referente a los tipos de variables. ¿Las variables locales en los pic de la gama alta se crean en el stack?.

Un saludo.

Si, es más, es así en cualquier compilador que conozco.   No he revisado declararlas como static dentro de una función pero supongo que también la agregará al stack.

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

  • Moderadores
  • DsPIC30
  • *****
  • Mensajes: 3595
Re: el tema de los punteros...
« Respuesta #20 en: 10 de Octubre de 2007, 15:36:23 »
Pues el CCS por lo menos en los pic de la gama baja no loa hace así, ademas no lo puede hacer ya que el stack solo tgiene 8 posiciones y son muy pocas para ademas utilizarlo en la declaración de variables locales (esta comprobado en el listado de ASM que genera).

Un saludo.
* Cuando hables, procura que tus palabras sean mejores que el silencio.
* 'Todos somos ignorantes, lo que ocurre es que no todos ignoramos las mismas cosas.' Albert Einstein.
* No hay nada peor que un experto para evitar el progreso en un campo
* "La vida es como una novela. No importa que sea larga, sino que esté bien narrada" Seneca
* La vida no se vive por las veces que respiras, sino por los momentos que dejan sin aliento.
* Dios dijo: ∇·E=ρ/ε0 ; ∇·B=0 ; ∇xE=-dB/dt ; ∇xB= μ0ε0dE/dt..y la luz se hizo..!!..

Desde España Jesús

Desconectado maunix

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 4751
    • Mi Sitio Web Personal
Re: el tema de los punteros...
« Respuesta #21 en: 10 de Octubre de 2007, 15:50:13 »
Pues el CCS por lo menos en los pic de la gama baja no loa hace así, ademas no lo puede hacer ya que el stack solo tgiene 8 posiciones y son muy pocas para ademas utilizarlo en la declaración de variables locales (esta comprobado en el listado de ASM que genera).

Un saludo.

Jesús, estamos hablando del stack pror software no? no del stack para los calls verdad?  Digo esto por la coincidencia entre las 8 posiciones que mencionas y los 8 niveles de stack de hardware para los calls de los 16F.

Solo puedo decir que se puede hacer de otra forma, usando variables 'overloaded' , o superpuestas y manejar así a las variables locales para evitar tanto trabajo con el stack pero esto lo veo 'demasiado peligroso' si una función llama a otra y a otra... o si algún llamado a función depende del resultado de un cálculo.  ¿cómo sabría el compilador si va a sobreescribir o no dicha región como para asumir ubicarla 'superpuesta' con otra?   No se, no me parece ni cerca la mejor solución pero si los de CCS lo usan...  :shock: :shock:  , espero documenten en su manual las severísimas condiciones que esto puede acarrear.

Todavía recuerdo el Reset_CPU que en los 16F, según un código que subió Diego (RedPic) compilaba como un goto 0x0000 lo cual es hasta gracioso.

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 RICHI777

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1498
Re: el tema de los punteros...
« Respuesta #22 en: 10 de Octubre de 2007, 18:48:11 »
Normalmente las variables locales declaradas dentro de una función como static, no son otra cosa que variables globales. Con respecto a un comentario sobre el uso del Stack, el tema se maneja asi:
1. Si la arquitectura del micro tiene acceso y buen manejo de Stack, los parametros de las funciones, las variables locales y el retorno al llamador se hace sobre el stack, se conoce normalmente como "Stack Frame".
2. Existen ademas convenciones de llamadas donde algunos de estos se realizan sobre registros por cuestiones de optimizacion
3. En el caso donde la arquitectura no poseea una gran maniobrabilidad con el uso del Stack Pointer ( Ejemplo 8051 ) entonces el compilador y el linker arman un arbol de ejecucion y las variables locales son globales "compartidas", el arbol esta hecho de tal manera que dos variables locales dentro del mismo arbol de ejecucion nunca se pisen y los parametros se pasan por registros, ademas era posible una opcion de compilacion para instruir al mismo que el retorno al llamador se copiaba en variables locales, de esta manera y si tenias suficiente RAM tu "Max-Depth"( Maxima profundidad de llamada ) no estaba limitado por la  arquitectura.
Ejemplos de estos ultimos IAR para 8051 y derivados.

Estas son las razones por la cual FreeScale ( Ex Motorola ) tira a la basura la famila HC05 y la reemplazo por la HC08 justamente por no tener manejo de Stack y entonces no poder soportar compiladores "C".

Saludos a todos !

Desconectado pajaro

  • PIC24H
  • ******
  • Mensajes: 1121
Re: el tema de los punteros...
« Respuesta #23 en: 03 de Mayo de 2009, 20:38:16 »
hola amigos

amigo PalitroqueZ puedes revisar
algunos pos de este hilo, por el principio hay fotos que no aparecen
podrian reenlazarlas.

Magnificas estas explicaciones, saberes muy buenos.

Un saludo.
« Última modificación: 10 de Septiembre de 2009, 10:20:00 por pajaro »

Desconectado PalitroqueZ

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5474
    • Electrónica Didacta
Re: el tema de los punteros...
« Respuesta #24 en: 04 de Mayo de 2009, 18:21:55 »
Este Artículo también se encuentra en ucontrol:

http://www.ucontrol.com.ar/wiki/index.php/CCS_-_Punteros



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

Desconectado xarox

  • PIC10
  • *
  • Mensajes: 21
Re: el tema de los punteros...
« Respuesta #25 en: 08 de Agosto de 2009, 18:45:55 »
Hay alguna manera de manejar un puntero de bits, si tengo una variable X y quiero leer el estado de los bits de la variable X con un for ¿Alguien sabe como hacerlo?

Desconectado Suky

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: el tema de los punteros...
« Respuesta #26 en: 08 de Agosto de 2009, 19:14:27 »
Puedes rotar y aplicar And:

Ejemplo, se lee el bit 3 y bit 5:

Byte>>3;
Bit=Byte&&0x01;
Byte>>2;
Bit=Byte&&0x01;

Saludos!
No contesto mensajes privados, las consultas en el foro

Desconectado al9

  • PIC10
  • *
  • Mensajes: 16
Re: el tema de los punteros...
« Respuesta #27 en: 12 de Agosto de 2009, 15:14:25 »
Hola.
Respecto a los punteros con cadenas, a ver que opinais de esta rutina y por que no funciona:

Código: C
  1. void displayString(char *x){
  2. int8 n;
  3. n=0;
  4.          i2cSTART();
  5.          while(x[n]!=0){
  6.             i2cWChar(x[n]);   //envia
  7.             n++;
  8.          }
  9.          i2cSTOP();
  10. ..
  11. ..
  12. void main()¨{
  13.   displayString("HOLA");
  14.  
  15. }
.. lastima que no vaya pues es muy elegante llamar asi a una funcion...

Las preguntas son:
¿En C las cadenas no acaba con el byte=0?
¿Que hacemos cuando llamamos a un procedimiento y ponemos las variables en el código?

Gracias.

Desconectado migsantiago

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8257
    • Sitio de MigSantiago
Re: el tema de los punteros...
« Respuesta #28 en: 12 de Agosto de 2009, 16:23:22 »
Esto es inválido en cualquier compilador de C:

Código: [Seleccionar]
displayString("HOLA");
Debes armar el string y después pasar un puntero.

Código: [Seleccionar]
char temp[10];
...
sprintf(temp,"Hola");
displayString(temp);

Desconectado Suky

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: el tema de los punteros...
« Respuesta #29 en: 12 de Agosto de 2009, 16:42:13 »
Pero en CCS esto creo que funcionaria:

Código: C
  1. void displayString(char x){
  2.      i2cWChar(x);   //envia
  3. }
  4. void main(){
  5.     i2cSTART();
  6.     displayString("HOLA");  
  7.     i2cSTOP();
  8. }
No contesto mensajes privados, las consultas en el foro


 

anything