Home > OS >  Why am I getting this output from a C union with bitfields in my code?
Why am I getting this output from a C union with bitfields in my code?

Time:12-17

Sorry for the non descriptive title - I wasn't sure how to pose this in one line.

I have a data structure, where I have two values: one 14-bit, one 10-bit. I want to be able to access them as bytes in a union. I have the following:

struct test
{
    union
    {
        struct
        {
            unsigned int a : 14;
            unsigned int b : 10;
        } fields;
        
        struct
        {
            unsigned char i0;
            unsigned char i1;
            unsigned char i2;
        } bytes;
    } id;
};

Now, when I assign 1 to the value at bytes.i2, I would expect the value at values.b to also assume the value 1. But the value in values.b is actually bytes.i2 shifted left by 2 bits.

int main()
{
    struct test x;
    x.id.bytes.i2 = 1;
    printf("%d", x.id.fields.b); // OUTPUTS 4
    return 0;
}

I must be missing some basic principle here, any insight would be helpful!

CodePudding user response:

In little endian, packed structs:

fields a              |b
bytes  i0      |i1    :  |i2
BITS   00000000|000000|00|10000000 i2 = 1; b = 4
BITS   00000000|000000|10|10000000 i1 = 64; b = 1
INDEX  01234567|890123|45|67890123
       0          1           2

As you can see b = 0b00000100 (4)

CodePudding user response:

The exact layout and ordering of bitfields in a struct is entirely up to the implementation.

On a little endian machine, the layout of the union most likely looks like this:

|a              |b   a          |b              |
|7 6 5 4 3 2 1 0|1 0 d c b a 9 8|a 9 8 7 6 5 4 3|
|      i0       |      i1       |       i2      |
-------------------------------------------------
| | | | | | | | | | | | | | | | | | | | | | | | |
-------------------------------------------------

In this layout, we can see that the 8 low order bits of a are in the first byte, then the 6 high order bits of a and the 2 low order bits of b in the second byte, followed by the high order 8 bits of b in the third byte. This explains the result you're seeing.

Little endian machine will typically also have the bits in little endian format, so if you reverse the order of the bits in each byte above, reflecting the physical representation instead of the logical representation, you can see that the bits of each bitfield are contiguous.

  • Related