Search code examples
cgccassertbit-fieldsunions

bitfields not working as expected in an union


Could anyone please tell me why is the assert failing ?

FYI: I'm compiling this using gcc 4.6.1 on a 64-bit linux machine.

typedef union cpu_register {
    uint64 _64;
    uint32 _32;
    uint16 _16;
    uint16 _8l : 8,
           _8h : 8;
} __attribute__((packed)) cpu_register;

int main()
{
    cpu_register reg;
    reg._64 = 1;
    assert(reg._8h != reg._8l);
    return 0;
}

The value expected for reg._8h is 0 but it is same as that of reg._8l (== 1).

I got a solution to overcome this issue, but I want to know what is wrong?


Solution

  • It looks like you wanted

    uint16 _8l : 8,
           _8h : 8;
    

    to be the low and high bits of a 16-bit integer.

    But these are in a union, and each element of a union in-effect stands for the entire union. So they each refer to the same 8 bits.

    You need to wrap them in a structure:

    struct {
        uint16 _8l : 8,
               _8h : 8;
    }
    

    and then put this structure into the union.