Sunday, August 17, 2014

where to use UNION (enga thaan union use pandranga :P)

Union:


typedef struct {
    int typ;
    union {
        char *str;
        int   val;
    }
} tElem;


Memory representaion of union (overlapping memory)


       +-----------+
0x1010 |           |
0x1011 |    typ    |
0x1012 |           |
0x1013 |           |
       +-----+-----+
0x1014 |     |     |
0x1015 | str | val |
0x1016 |     |     |
0x1017 |     |     |
       +-----+-----+


Memory representation if its structure:(contiguous memory)



       +-------+
0x1010 |       |
0x1011 |  typ  |
0x1012 |       |
0x1013 |       |
       +-------+
0x1014 |       |
0x1015 |  str  |
0x1016 |       |
0x1017 |       |
       +-------+
0x1018 |       |
0x1019 |  val  |
0x101A |       |
0x101B |       |
       +-------+



purpose of union:

  • This allows the size of struct S to be only 12 bytes, instead of 28.
  • implement pseudo-polymorphism in C



enum Type { INTS, FLOATS, DOUBLE };
struct S
{
  Type s_type;
  union
  {
    int s_ints[2];
    float s_floats[2];
    double s_double;
  };
};

void do_something(struct S *s)
{
  switch(s->s_type)
  {
    case INTS:  // do something with s->s_ints
      break;

    case FLOATS:  // do something with s->s_floats
      break;

    case DOUBLE:  // do something with s->s_double
      break;
  }
}



  • 've seen it in a couple of libraries as a replacement for object oriented inheritance.
    E.g.
            Connection
         /       |       \
      Network   USB     VirtualConnection
    If you want the Connection "class" to be either one of the above, you could write something like:
    struct Connection
    {
        int type;
        union
        {
            struct Network network;
            struct USB usb;
            struct Virtual virtual;
        }
    };
  • Unions are particularly useful in Embedded programming or in situations where direct access to the hardware/memory is needed. Here is a trivial example:
  • typedef union
    {
        struct {
            unsigned char byte1;
            unsigned char byte2;
            unsigned char byte3;
            unsigned char byte4;
        } bytes;
        unsigned int dword;
    } HW_Register;
    HW_Register reg;
    Then you can access the reg as follows:
    reg.dword = 0x12345678;
    reg.bytes.byte3 = 4;
    Endianness (byte order) and processor architecture are of course important.

  • you can access directly a single bit in the register/memory address:
  • typedef union
    {
        struct {
            unsigned char b1:1;
            unsigned char b2:1;
            unsigned char b3:1;
            unsigned char b4:1;
            unsigned char reserved:4;
        } bits;
        unsigned char byte;
    } HW_RegisterB;
    HW_RegisterB reg;
    With this code you can access directly a single bit in the register/memory address:
    x = reg.bits.b2;
  • you're only supposed to read the field which was most recently written in the union



Resource:

No comments:

Post a Comment