Search code examples
c++cstructunions

what does a unioned struct do?


I have no idea how to decipher this man someone needs to tell me what is going on please help

typedef struct _ARGBCOLOR {
    union {
        struct {
            BYTE B;
            BYTE G;
            BYTE R;
            BYTE A;
        };
        DWORD ARGB;
    };
} ARGBCOLOR, *PARGBCOLOR;

Solution

  • If you have a ARGBCOLOR x;You can access 4 separate bytes as x.B,x.G,x.R, and x.A, or a 32-bit word as x.ARGB.

    The C standard guarantees these will overlay properly (assuming the sizes fit and padding requirements don't screw the pooch (not the case here)). But this struct clearly assumes a little-endian system.

    One extra complication is that the union is anonymous. It's common to name a union like this u, but some compilers allow internal unions and structs to be anonymous, so its members are accessed as if they were up one level (at the same level as the union itself).

    My favorite way to do this sort of overlay type is to put the union at the outermost level. You can duplicate the kind or type member so it's accessible everywhere. But this way removes the temptation to use anonymous unions (which are not available in Ansi-C or C99) because you don't need a bogus u member in the middle.

    typedef union _ARGBCOLOR {
        //BYTE type;
        struct {
            //BYTE type;
            BYTE B;
            BYTE G;
            BYTE R;
            BYTE A;
        } bytes;
        struct {
            //BYTE type;
            DWORD ARGB;
        } word;
    } ARGBCOLOR, *PARGBCOLOR;
    

    Due to the common initial prefix property, all three of the BYTE type; members would overlay the same memory.

    Another variation is to make an array for the individual bytes.

    typedef union _ARGBCOLOR {
        DWORD dword;
        BYTE byte[ sizeof(DWORD)/sizeof(BYTE) ];
    } ARGBCOLOR, *PARGBCOLOR;
    enum { B,G,R,A };
    

    Now we don't need two levels, and the type-punning is more apparent.

    ARGBCOLOR x = { 0x10203040 };
    x.byte[B] = 50;
    x.byte[G] = 60;
    printf("0x%8x\n", x.dword);  // prints: 0x10206050