Search code examples
cunionsbit-fields

Bitfield union for easy bit access, unexpected behavior


I made this union, in order to easily access, back and forth, between bits and integer. (in fact, I looked for a way to r/w all bits of a signed int, easily, without portability pitfall, I screwed myself nicely)

typedef union {
    struct {
         unsigned int b32   : 1;
         unsigned int b31   : 1;
         unsigned int b30   : 1;
         unsigned int b29   : 1;
         unsigned int b28   : 1;
         unsigned int b27   : 1;
         unsigned int b26   : 1;
         unsigned int b25   : 1;
         unsigned int b24   : 1;

         /* etc. */

         unsigned int b01   : 1; /* LSB */
    } field;
    uint32_t word;
    int32_t integer;
} Bit32Field_T;

As expected, each bxx field give me access to the bits of the underlying 32 byte integer.

This code however, is only valid for a sparc (big endian) CPU. For little-endian ones (x86) I have to mirror each fields, from b01 to b32, in order to get the expected behavior.

typedef union {
    struct {
         unsigned int b01   : 1; /* LSB */
         unsigned int b02   : 1;
         unsigned int b03   : 1;
         unsigned int b04   : 1;
         unsigned int b05   : 1;
         unsigned int b06   : 1;
         unsigned int b07   : 1;
         unsigned int b08   : 1;
         unsigned int b09   : 1;

         /* etc. */

         unsigned int b32   : 1;
    } field;
    uint32_t word;
    int32_t integer;
} Bit32Field_T;

I thought little-endianness was about reversing bytes not bits ! How should I understand the bit packing made ?

(everything compiled with gcc, under solaris for the BE, debian for the LE)


Solution

  • My approach for a similar problem, i.e. converting a 32 bit word from little to big-endian, was:

    unsigned char buf[4];
    uint32_t word;
    
    fread(buf, sizeof(buf), 1, fp);
    
    word = buf[0] |
        (buf[1] << 8) |
        (buf[2] << 16) |
        (buf[3] << 24);
    

    I agree it is bizarre that your code worked, I would have expected the approach suggested by Pickif would be what is required

    Prob worth taking M Oehm s advice on extracting bits if it is compiler dependent and not something to do with the hardware and ditch the union approach