Search code examples
cgccstructunions

Using UNIONs and STRUCTUREs


Is this approach correct?

struct netinfo
{
   // a lot of members here...
   union
   {
     UINT type;
     struct
     {
        UINT   _type;    // a place holder (obviously who access this struct already knows the type is ipv4)
        UINT32 saddr;
        UINT32 daddr;
        UINT   ttl.
     } ip4;
     struct
     {
       UINT  _type;        // a place holder (obviously who access this struct already knows the type is ipv6)
       UINT8 saddr[16];
       UINT8 daddr[16];
     } ip6;
  }  protocol;
  // a lot of members here...
};

struct netinfo my_netinfo;

my_netinfo.protocol.type = NETTYPE__IPV4; // note that i used the "protocol" union as the "type"  member
my_netinfo.protocol.ip4.saddr = addr1;     // now i'm accessing the union as the  "ip4" member
my_netinfo.protocol.ip4.daddr = addr2;
my_netinfo.protocol.ip4.ttl = 64;

// ...

// later, i pretend to acess protocol.type and protocol.ip4.X, the way i want

Note that my intention is access it as, AT THE SAME TIME:

my_netinfo.protocol.type and my_netinfo.protocol.ip4

I will not use my_netinfo.protocol.ip4.type, because by accessing my_netinfo.protocol.ip4, I already know i'm dealing with IPv4.

The question is:

By using the _type in the structures, as its first members, will this approach be valid and a good idea?

union { int x; struct { int _padding_for_x; int a; int b; } y };

This way union_namex, union_name.y.a, union_namey.y.b, union_name.x again...

Can I write/read/write/read again all of them in any order?


Solution

  • The answer is no and no.

    The standard requires that only one of the members of a union be active at a time. There is an exemption that would allow you to inspect the common initial sequence (UINT _type) but the other members cannot be active at the same time. A program that does so is ill-formed (which is just as bad as Undefined Behaviour).

    Not only is it theoretically bad, but practically bad as well. The alignment possibilities make it almost impossible to predict the layout of that union. Your data is in there somewhere, but only the compiler and its maker know where.

    So no, it isn't a good idea either.