Justin Dobson
Justin Dobson

Reputation: 63

How does this Union and Bit field interaction work?

So here is an example:

struct field
{
    unsigned int a : 8;
    unsigned int b : 8;
    unsigned int c : 8;
    unsigned int d : 8;
};

union test
{
    unsigned int raw;
    field bits;
};

int main()
{

    test aUnion;
    aUnion.raw = 0xabcdef;

    printf("a: %x \n", aUnion.bits.a);
    printf("b: %x \n", aUnion.bits.b);
    printf("c: %x \n", aUnion.bits.c);
    printf("d: %x \n", aUnion.bits.d);


    return 0;
}

now running this I get:

a: ef
b: cd
c: ab
d: 0

And I guess I just dont really get whats happening here. So I set raw to a value, and since this is a union, everything else pulls from that since they have all been set to be smaller than an unsigned int? so the bit field is based on raw? but how does that map out? why is d: 0 in this instance?

I would appreciate any help here.

Upvotes: 1

Views: 514

Answers (2)

Roberto Caboni
Roberto Caboni

Reputation: 7490

Using hexadecimal representation of an integer is useful because it makes clear what is the value of every byte of the integer. So the setting

aUnion.raw = 0xabcdef;

means that the value of least significant byte is 0xef, that the second least significant byte has value 0xcd and so on. But you are setting the raw field of the union, that is an integer so it is 4 bytes long. In the previous representation the most significant byte is missing, so it can be written as

aUnion.raw = 0x00abcdef;

(it is like making explicit that an integer x = 42 has 0 hundreds, 0 thousands and so on).

Your union fields represent respectively a =byte[0], b = byte[1], c = byte[2] and d = byte[3] of the integer raw, since in a union all the elements share the same memory location. This is true because you are running your code in a little endian architecture (least significant bytes come first).

So:

a = byte[0] of raw = 0xef
b = byte[1] of raw = 0xcd
c = byte[2] of raw = 0xab
d = byte[3] of raw = 0x00

Upvotes: 2

Inian
Inian

Reputation: 85885

Its because your unsigned int isn't 32 bit long enough (all 32 bits not set) to completely fill all the bit field values. Because it only 24 bits long, the bit field d is showing hex value of 00 . Try it for e.g.

aUnion.raw = 0xffabcdef;

which will produce

a: ef 
b: cd 
c: ab 
d: ff

Since the dd bit field occupies bits 24-32 (on little endian), unless the assigned unsigned int field has been assigned a value that occupies those bits set, that bit field position doesn't show the value too.

Upvotes: 2

Related Questions