Search code examples
c++structunionsbit-fields

difference between union of fields and union of structures


I'm defining a group of structs to handle some registers and when I defined the structs I found this difference between defining a union of simple fields and union of structs. I'm not sure why this difference happens:

#include <iostream>

using namespace std;


typedef union
{

    uint16_t all_bits;
    struct
    {   
        uint16_t a:4, b:4, c:4, d:3, e:1;
    };  
}
Example1_t;

typedef union
{

    uint16_t all_bits;
    uint16_t a:4, b:4, c:4, d:3, e:1;

}
Example2_t;

    int 
main ()
{
    Example1_t example1;
    Example2_t example2;
    example1.all_bits = 0x8BCD;
    example2.all_bits = 0x8BCD;

    cout << "a " << std::hex << example1.a << " " << example2.a << std::endl;
    cout << "b " << std::hex << example1.b << " " << example2.b << std::endl;
    cout << "c " << std::hex << example1.c << " " << example2.c << std::endl;
    cout << "d " << std::hex << example1.d << " " << example2.d << std::endl;
    cout << "e " << std::hex << example1.e << " " << example2.e << std::endl;

    return 0;
}

OUTPUT:

a d d                                                                                                                                        
b c d                                                                                                                                        
c b d                                                                                                                                        
d 0 5                                                                                                                                        
e 1 1   

Solution

  • The pedantic answer is:

    Your code has Undefined Behavior. Writing to a union field and reading from another is not guaranteed to work, so any inconsistency you see can be handwaved away as "broken code".

    In actuality, so many people in the wild rely on this "broken behavior" being consistent that all modern compilers still provide predictable functionality here (at the cost of ignoring some optimization opportunities). So there is indeed something specific in your code that is making it behave the way it does:

    In Example1_t, the union has two overlapping fields: all_bits and the struct. Within that struct, each member has distinct storage.

    In Example2_t, a, b, c, d and e are all separate fields of the union, so they all have overlapping storage.