Autor Tema: Duda con uniones y estructuras en c  (Leído 6367 veces)

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

Desconectado pandemonium

  • PIC10
  • *
  • Mensajes: 14
Duda con uniones y estructuras en c
« en: 04 de Febrero de 2011, 21:50:41 »
Un cordial saludo a los Maestros y a todos los foreros de este gran foro  :). Estoy usando en estos momentos el compilador CCS 4.108 y me ha surgido una duda respecto a la sintaxis de C con las uniones. Resulta que escribo el siguiente codigo para poder acceder facilmente a a la variable "union_t":

Código: [Seleccionar]

typedef union{

     uint8_t val;
     struct{
          uint8_t   b0   :1;
          uint8_t   b1   :1;
          uint8_t   b2   :1;
          uint8_t   b3   :1;
          uint8_t   b4   :1;
          uint8_t   b5   :1;
          uint8_t   b6   :1;
          uint8_t   b7   :1;
     };
}uint8_bits;


void main(void){
 
 uint8_bits union_t;
 union_t.val = 48;

}



Como ven, la manera genérica d acceder a la variable es como se muestra arriba. Si quiero acceder al bit 6 de "union_t" solamente necesito escribir

Código: [Seleccionar]

union_t.b6 = true; //false



esto se logra dejando la estructura que esta anidada en la union sin nombres. Para los que depronto no saben esto se conoce como "estructuras anonimas".


Ahora bien, la duda surge cuando compilo el programa siguiente:

Código: [Seleccionar]

typedef union{

     uint8_t val;
     struct{
          uint8_t   b0   :1;
          uint8_t   b1   :1;
          uint8_t   b2   :1;
          uint8_t   b3   :1;
          uint8_t   b4   :1;
          uint8_t   b5   :1;
          uint8_t   b6   :1;
          uint8_t   b7   :1;
     };
}uint8_bits;


void main(void){
 
 uint8_bits union_t;
 union_t = 48;

}


Como acaban de ver puedo asignar el numero directamente en "union_t" y me compila perfectamente. No se hizo necesario el uso del operador "."(punto). Inclusive, revise el ensamblador arrojado y todo va perfecto. La pregunta es: Esto es legal? Es ANSI ?. me he quedado todo un dia tratando de averiguarlo pero no llego mas alla de lo comentado sobre la sintaxis general. Agradeceria una respuesta.

PD: Disculpen mi mala ortografia con la falta de tildes pero estoy usando un teclado desde un servidor synergy que uso para compartir teclado y mouse y no he podido configurar bien el PC cliente.  :5]


« Última modificación: 04 de Febrero de 2011, 21:55:37 por pandemonium »

Desconectado AngelGris

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2480
Re: Duda con uniones y estructuras en c
« Respuesta #1 en: 04 de Febrero de 2011, 23:26:31 »
  Una pregunta, ¿uint8_t es algún tipo que hayas definido con anterioridad? Porque quise compilar tu código con HiTech -que supuestamente es ANSI C- y me tiró varios errores.

  Reemplacé uint8_t por char (que sé que es un tipo de variable que tiene HiTeh) y compiló bien excepto la línea

Código: C
  1. union_t = 48;

  pero si cambio dicha línea por la siguiente sí compila bien

Código: C
  1. union_t.val = 48;
De vez en cuando la vida
nos besa en la boca
y a colores se despliega
como un atlas

Desconectado Suky

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: Duda con uniones y estructuras en c
« Respuesta #2 en: 05 de Febrero de 2011, 00:46:53 »
  Una pregunta, ¿uint8_t es algún tipo que hayas definido con anterioridad? Porque quise compilar tu código con HiTech -que supuestamente es ANSI C- y me tiró varios errores.
 

Exactamente, es un typedef anterior  ;-)


pandemonium, entiendo que no es ANSI C, bueno de CCS no se puede esperar menos  :D


Es como si fuera una class y se asignara el operador = o algo por estilo  :shock:


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

Desconectado pandemonium

  • PIC10
  • *
  • Mensajes: 14
Re: Duda con uniones y estructuras en c
« Respuesta #3 en: 05 de Febrero de 2011, 13:45:59 »
Hola de nuevo Maestros. Si, efectivamente como dice el Maestro Suky, la variable uint8_t es un:
Código: [Seleccionar]

typedef unsigned char   uint8_t;



razones del uso?. Basicamente quiero empezar a hacer una programacion mas generica, mas tirada al ANSI, entonces escribi un fichero .h que contiene las definiciones de tipos para usarlas indistintamente del compilador. Ahhhh que va, aqui les comparto el codigo que no es nada del otro mundo por si lo necesitan:
Código: [Seleccionar]
/********************************************************************************

* Copyright (c) 2010 Julian Ramirez "pandemonium"

* All rights reserved.

*

* Redistribution and use in source and binary forms, with or without

* modification, are permitted provided that the following conditions

* are met:

* 1. Redistributions of source code must retain the above copyright

*    notice, this list of conditions and the following disclaimer.

* 2. Redistributions in binary form must reproduce the above copyright

*    notice, this list of conditions and the following disclaimer in the

*    documentation and/or other materials provided with the distribution.

* 3. Neither the name of copyright holders nor the names of its

*    contributors may be used to endorse or promote products derived

*    from this software without specific prior written permission.

*

* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS

* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED

* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR

* PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL COPYRIGHT HOLDERS OR CONTRIBUTORS

* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE

* POSSIBILITY OF SUCH DAMAGE.

*

**************************************************************************

*                             generic_types.h

*

* COMENTARIOS: Implementacion de macros y definiciones para estandarizar

*              tipos de datos para el uso de fuciones con multiples

*              compiladores.

*

*

**************************************************************************

* Programador: Julián Ramirez "pandemonium".

* Compiladores: CCS PCWHD C, HITECH C, C18, C30, MIKROC.

* Dependencias: no.

* Procesadores: PIC12*, PIC16*, PIC18*, PIC24*, dsPIC.

*

*  Cambios Historia:

*   Rev   Fecha         Descripcion

*   1.0   03/01/10     Definicion de tipos de datos genericos y tablas de bits

*   

**************************************************************************/



#ifndef __GENERIC_TYPES_H_

     #define __GENERIC_TYPES_H_

#endif





/* obtener los tipos da datos especificos del compilador (NULL, size_t, etc) */

#if !defined(__MIKROC_PRO_FOR_PIC__)

     #include <stddef.h>

#endif



#define void                    VOID

#define PRIVATE                 static





#if   defined(__PICC__)           /* HT-PICC10/12/16        */



typedef bit                   boolean_t;

typedef signed char           char_t,             int8_t;

typedef signed int            int_t,              int16_t;

typedef signed short          short_t;

typedef signed short long     short_long_t,       int24_t;

typedef signed long           long_t,             int32_t;

typedef float                 float_t;

typedef double                double_t;



typedef unsigned char         uchar_t,            uint8_t;

typedef unsigned int          uint_t,             uint16_t;

typedef unsigned short        ushort_t,           d_word;

typedef unsigned short long   ushort_long_t,      uint24_t;

typedef unsigned long         ulong_t,            uint32_t,           q_word;





//------------------------------------------------------------------------------



#elif   defined(__PICC18__)           /* HT-PICC18        */



typedef bit                   boolean_t;

typedef signed char           char_t,             int8_t;

typedef signed int            int_t,              int16_t;

typedef signed short          short_t;

typedef signed short long     short_long_t,       int24_t;

typedef signed long           long_t,             int32_t;

typedef float                 float_t;

typedef double                double_t;



typedef unsigned char         uchar_t,            uint8_t;

typedef unsigned int          uint_t,             uint16_t;

typedef unsigned short        ushort_t,           d_word;

typedef unsigned short long   ushort_long_t,      uint24_t;

typedef unsigned long         ulong_t,            uint32_t,           q_word;





//------------------------------------------------------------------------------





#elif defined(__18CXX)              /* Microchip C18    */



typedef signed char           char_t,             int8_t;

typedef signed int            int_t,              int16_t;

typedef signed short          short_t;

typedef signed short long     int24_t;

typedef signed long           long_t,             int32_t;

typedef float                 float_t;



typedef unsigned char         uchar_t,            uint8_t;

typedef unsigned int          uint_t,             uint16_t;

typedef unsigned short        ushort_t,           d_word;

typedef unsigned short long   uint24_t;

typedef unsigned long         ulong_t,            uint32_t,           q_word;





//------------------------------------------------------------------------------



#elif defined(__C30__)              /* Microchip C30    */



typedef signed char           char_t,             int8_t;

typedef signed int            int_t,              int16_t;

typedef signed short          short_t;

typedef signed long           long_t,             int32_t;

typedef signed long long      long_long_t,        int64_t;

typedef float                 float_t;

typedef long double           double_t;



typedef unsigned char         uchar_t,            uint8_t;

typedef unsigned int          uint_t,             uint16_t;

typedef unsigned short        ushort_t,           d_word;

typedef unsigned long         ulong_t,            uint32_t,           q_word;

typedef unsigned long long    ulong_long_t,       uint64_t;

   

//------------------------------------------------------------------------------



#elif defined(__PCB__) || defined(__PCM__) || defined(__PCH__)             /* CCS para PIC18 o PIC16 */



typedef int1                  boolean_t;

typedef signed char           char_t;

typedef signed int            int8_t;

typedef signed long           int_t,              int16_t,            short_t;

typedef signed long long      long_t,             int32_t;

typedef float                 float_t;



typedef unsigned char         uchar_t;

typedef unsigned int          uint8_t;

typedef unsigned long         uint_t,             uint16_t,           ushort_t,           d_word;

typedef unsigned long long    ulong_t,            uint32_t,           q_word;





//------------------------------------------------------------------------------



#elif defined(__PCD__)



typedef signed char           char_t;

typedef signed short          int8_t;

typedef signed int            int_t,              int16_t,            short_t;

typedef signed long           long_t,             int32_t;

typedef signed long long      long_long_t,        int64_t;

typedef float                 float_t;

typedef long double           double_t;



typedef unsigned char         uchar_t;

typedef unsigned short        uint8_t;

typedef unsigned int          uint_t,             uint16_t,           ushort_t,           d_word;

typedef unsigned long         ulong_t,            uint32_t,           q_word;

typedef unsigned long long    ulong_long_t,       uint64_t;

   



//------------------------------------------------------------------------------

#elif defined(__MIKROC_PRO_FOR_PIC__)

       

typedef signed char           char_t;

typedef signed short          int8_t;

typedef signed int            int_t,              int16_t,            short_t;

typedef signed long int       long_t,             int32_t;

typedef float                 float_t;

typedef double                double_t;



typedef unsigned char         uchar_t;

typedef unsigned short        uint8_t;

typedef unsigned int          uint_t,             uint16_t,           ushort_t,           d_word;

typedef unsigned long int     ulong_t,            uint32_t,           q_word;



   

//------------------------------------------------------------------------------

//#elif defined(__AVR__)

 

//------------------------------------------------------------------------------

//#elif defined(__ICCAVR__)

   

//------------------------------------------------------------------------------



#endif



#if defined(__C18xx) || defined(__C30__) || defined(__PCD__)



#ifdef false

    #undef false

#endif





#ifdef true

    #undef true

#endif





typedef enum _BOOL{ false=0, true} boolean_t;    // Undefined size

typedef enum _BIT{ clear=0, set} bit_t;



#define false               0

#define true                1



#endif





#if defined(__MIKROC_PRO_FOR_PIC__)



typedef enum _BOOL{ false_t=0, true_t} boolean_t;    // Undefined size

typedef enum _BIT{ clear_t=0, set_t} bit_t;



#endif



typedef union{



     uint8_t data;

     struct{

          uint8_t   b0   :1;

          uint8_t   b1   :1;

          uint8_t   b2   :1;

          uint8_t   b3   :1;



          uint8_t   b4   :1;

          uint8_t   b5   :1;

          uint8_t   b6   :1;

          uint8_t   b7   :1;

     };

}uint8_bits;







typedef union{



     uint16_t  dword;

     uint8_t   a_byte[2];

     

     struct{

          uint8_t   byte_0;

          uint8_t   byte_1;

     };

     

     struct{

          uint8_t   b0   :1;

          uint8_t   b1   :1;

          uint8_t   b2   :1;

          uint8_t   b3   :1;

          uint8_t   b4   :1;

          uint8_t   b5   :1;

          uint8_t   b6   :1;

          uint8_t   b7   :1;

          uint8_t   b8   :1;

          uint8_t   b9   :1;

          uint8_t   b10  :1;

          uint8_t   b11  :1;

          uint8_t   b12  :1;

          uint8_t   b13  :1;

          uint8_t   b14  :1;

          uint8_t   b15  :1;

     };

}uint16_bits;





typedef union{



     uint32_t  qword;

     uint16_t  dword[2];

     uint8_t   a_byte[4];

     

     struct{

          uint16_t  l_word;

          uint16_t  h_word;

     };

     

     struct{

          uint8_t   byte_0;

          uint8_t   byte_1;

          uint8_t   byte_2;

          uint8_t   byte_3;

     };

     

     struct{

          uint8_t   b0   :1;

          uint8_t   b1   :1;

          uint8_t   b2   :1;

          uint8_t   b3   :1;

          uint8_t   b4   :1;

          uint8_t   b5   :1;

          uint8_t   b6   :1;

          uint8_t   b7   :1;

          uint8_t   b8   :1;

          uint8_t   b9   :1;

          uint8_t   b10  :1;

          uint8_t   b11  :1;

          uint8_t   b12  :1;

          uint8_t   b13  :1;

          uint8_t   b14  :1;

          uint8_t   b15  :1;

          uint8_t   b16  :1;

          uint8_t   b17  :1;

          uint8_t   b18  :1;

          uint8_t   b19  :1;

          uint8_t   b20  :1;

          uint8_t   b21  :1;

          uint8_t   b22  :1;

          uint8_t   b23  :1;

          uint8_t   b24  :1;

          uint8_t   b25  :1;

          uint8_t   b26  :1;

          uint8_t   b27  :1;

          uint8_t   b28  :1;

          uint8_t   b29  :1;

          uint8_t   b30  :1;

          uint8_t   b31  :1;

     };

}uint32_bits;







//-------------------------------------------------------------------

Con este codigo podemos acceder los bytes y los bits de las variables que declaremos de una manera mas rápida y sencilla sin tener que estar usando esas funciones incluidas en algunos compiladores que a la larga sólo nos genera dependencia.

Ahora bien, resulta que me surgió la duda inicial del post, pero veo que con el ejemplo del Maestro Angelgris ya está claro que acceder directamente a la union sin el uso del operador .(punto) no sólamente es ilegal sino que a mi parecer es garrafal el hecho de que funcione en ccs  :5]. Cada vez me convenzo mas de usar hitech C o c18. Pero la pega de siempre es su elevado precio :(

de todas formas gracias por su rápida respuesta, ya me quedó claro.
« Última modificación: 05 de Febrero de 2011, 13:49:17 por pandemonium »

Desconectado AngelGris

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2480
Re: Duda con uniones y estructuras en c
« Respuesta #4 en: 05 de Febrero de 2011, 14:00:20 »
  Yo hace rato que uso HiTech, pero siempre como hobby. Para los PIC de la serie 12 y 16 Descargué la versión PRO y luego de 45 días queda como Lite cuyas limitaciones son la optimización de código y algunas cosillas mas que no recuerdo. Pero no tiene limite en cuanto al largo del programa.

  Para los 18, luego de 45 días (creo) empezó a tirar algunos errores. Pero eliminé un archivo xml (uso linux) y ya no me jorobó más. Quizá en Windows haya que desinstalarlo, limpiar el registro y volver a instalarlo para tenerlo nuevamente funcional.
De vez en cuando la vida
nos besa en la boca
y a colores se despliega
como un atlas

Desconectado RICHI777

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1498
Re: Duda con uniones y estructuras en c
« Respuesta #5 en: 05 de Febrero de 2011, 17:42:01 »
Hola el manejo de campo de bits ( que es lo que estas haciendo ) en ingles se denomina bits field es totalmente válido para el ANSI C. El problema es que el estandart dice que la implementación del mismo, es decir el layout interno que tendrá los bits es plataforma dependiente. De esta manera podrías tener un campo de bits de 3 elementos que ocupen mas de un byte que sería lo lógico. Lo mismo ocurre con el posicionamiento, el compilador puede asignarlo donde quiera sin respetar el orden, por esto los campos de bits para acceder en forma individual si es portable, ahora para trabajar de a grupos o hacer conversiones no es recomendado.

Saludos !

Desconectado IST

  • PIC10
  • *
  • Mensajes: 3
Re: Duda con uniones y estructuras en c
« Respuesta #6 en: 16 de Mayo de 2011, 02:11:27 »
Buenas noches!! Estoy desarrollando un control para un motor paso a paso y quería armar un estructura para desentenderme de los pines del puerto que conecte al motor. Es decir, modificando unas definiciones el resto del programa seguiría igual.
Intenté realizarlo de la siguiente manera pero me da error de sintaxis . Quisiera saber si alguien me puede dar una mano... Está hecho en C18 y el pic es un 18f4550.
Desde ya gracias!!

Código: [Seleccionar]
#define P1Mas LATAbits.LATA4
#define P1Menos LATAbits.LATA5
#define P2Mas LATAbits.LATA6
#define P2Menos LATAbits.LATA7


union
{
unsigned char motor;
struct
{
unsigned P1Mas:1;
unsigned P1Menos:1;
unsigned P2Mas:1;
unsigned P2Menos:1;
unsigned :4;
}
}PaP;

Desconectado RICHI777

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1498
Re: Duda con uniones y estructuras en c
« Respuesta #7 en: 16 de Mayo de 2011, 10:43:27 »
Hola, me parece que te falta ponerle el nombre a la estructura.

Código: C
  1. #define P1Mas           LATAbits.LATA4
  2. #define P1Menos         LATAbits.LATA5
  3. #define P2Mas           LATAbits.LATA6
  4. #define P2Menos         LATAbits.LATA7
  5.  
  6.  
  7. union
  8. {
  9.         unsigned char motor;
  10.         struct
  11.         {
  12.                 unsigned P1Mas:1;                              
  13.                 unsigned P1Menos:1;
  14.                 unsigned P2Mas:1;
  15.                 unsigned P2Menos:1;
  16.                 unsigned :4;           
  17.         } Pirulo;      
  18. }PaP;

Desconectado Suky

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: Duda con uniones y estructuras en c
« Respuesta #8 en: 16 de Mayo de 2011, 10:59:37 »
No, así como lo planteas es imposible. Richi la estructura puede no tener nombre.

En p18f4550.h están definidas las estructuras de los registros del microcontrolador, en LATbits puedes cambiarlo a:


Código: C
  1. extern volatile near union{
  2.         struct{
  3.           unsigned LATA0:1;
  4.           unsigned LATA1:1;
  5.           unsigned LATA2:1;
  6.           unsigned LATA3:1;
  7.           unsigned LATA4:1;
  8.           unsigned LATA5:1;
  9.           unsigned LATA6:1;
  10.           unsigned LATA7:1;
  11.         };
  12.         struct{
  13.                 unsigned NoUsed:4;
  14.                 unsigned pin_4:1;
  15.                 unsigned pin_5:1;
  16.                 unsigned pin_6:1;
  17.                 unsigned pin_7:1;
  18.         }PAP;
  19. } LATAbits;

Y en código trabajarlo:

Código: C
  1. LATAbits.PAP.pin_4=1;
  2. LATAbits.PAP.pin_5=0;
  3. LATAbits.PAP.pin_6=1;
  4. LATAbits.PAP.pin_7=0;


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

Desconectado RICHI777

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1498
Re: Duda con uniones y estructuras en c
« Respuesta #9 en: 16 de Mayo de 2011, 11:22:41 »
Hola Suky, gracias por el dato, contesté eso porque ANSI C no soporta estructuras anónimas y creía que el C18 era mas ANSI que CCS.

Saludos !

Desconectado IST

  • PIC10
  • *
  • Mensajes: 3
Re: Duda con uniones y estructuras en c
« Respuesta #10 en: 16 de Mayo de 2011, 11:39:01 »
Muchas gracias por responder!! Lo pruebo y les cuento como me va...
Saludos!!

Desconectado Suky

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: Duda con uniones y estructuras en c
« Respuesta #11 en: 16 de Mayo de 2011, 13:22:52 »
Hola Suky, gracias por el dato, contesté eso porque ANSI C no soporta estructuras anónimas y creía que el C18 era mas ANSI que CCS.

Saludos !
Por suerte si lo soporta!  :D Y C18 es muuuucho más ANSI C que CCS  ;-)


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

Desconectado IST

  • PIC10
  • *
  • Mensajes: 3
Re: Duda con uniones y estructuras en c
« Respuesta #12 en: 16 de Mayo de 2011, 19:27:08 »
Hola Suky, seguí tus consejos y lo hice como me dijiste, pero después quise hacer un define para llamar a cada bit de una forma mas corta y me da el siguiente error:
Error [1105] symbol 'P1Menos' has not been defined
Error [1101] lvalue required


Código: [Seleccionar]
#define P1Menos1 LATAbits.PAPA.P1menos
Si en vez de usar P1Menos1 uso LATAbits.PAPA.P1menos compila sin problemas.
Alguna idea de por que pasa esto?
Gracias!!

Desconectado Suky

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: Duda con uniones y estructuras en c
« Respuesta #13 en: 16 de Mayo de 2011, 20:05:57 »
 :shock: Ni idea, incluí el p18F4550.h al proyecto, por las dudas.


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