Virus721 Virus721 - 4 years ago 79
C Question

Endianness and unions of primitive / object with bitfields

I have an union that allows me to easily set/unset bits and modify values (groups of bits) inside a uint32_t value without having to use masks and shifting :

union
{
struct ObjVal
{
uint32_t field0 : 1;
uint32_t field1 : 3;
uint32_t field2 : 12;
uint32_t field3 : 1;
uint32_t field4 : 1;
uint32_t field5 : 1;
uint32_t field6 : 1;
uint32_t unused : 4;
}
obj;

uint32_t raw;
}


My question is : is
field0
placed on the high-order side of the
uint32_t
value ? More precisely : if I set
field0
to
1
, will I get a raw value of
1
or will I get
1 << 31
?

I was thinking that, setting the first declared field would set the higher order bits, but after some tests it seems like it's the lower order bits that are set.

So my second question is : is this endianness and/or compiler dependant ?

Thank you.

Answer Source

It is endian dependent. For example, here's the definition of the IPv4 header from /usr/include/netinet/ip.h on my Linux system:

struct iphdr
  {
#if __BYTE_ORDER == __LITTLE_ENDIAN
    unsigned int ihl:4;
    unsigned int version:4;
#elif __BYTE_ORDER == __BIG_ENDIAN
    unsigned int version:4;
    unsigned int ihl:4;
#else
# error "Please fix <bits/endian.h>"
#endif
    u_int8_t tos;
    u_int16_t tot_len;
    u_int16_t id;
    u_int16_t frag_off;
    u_int8_t ttl;
    u_int8_t protocol;
    u_int16_t check;
    u_int32_t saddr;
    u_int32_t daddr;
    /*The options start here. */
  };
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download