Order of fields when using a bit field in C
I have a struct of the following type
typedef struct
{
unsigned int a : 8;
unsigned int b : 6;
unsigned int c : 2;
}x, *ptr;
What i would like to do, is change the value of field c.
I do something like the following
x structure = { 0 };
x->c = 1;
When I look at the memory map, I expect to find 00 01, but instead I find 00 40. It looks like when arranging the second byte, it puts c field in the lowest bits and b field in the highest bits. I've seen this on both GCC and Windows compilers.
For now, what I do is the following, which is working OK.
unsigned char ptr2 = (unsigned char*) ptr
*(ptr2 + 1) &= 0xFC
*(ptr2 + 1) |= 0x01
Am I looking at the memory map wrong? Thank you for your help.
C standard allows compiler to put bit-fields in any order. There is no reliable and portable way to determine the order.
If you need to know the exact bit positions, it is better use plain unsigned variable and bit masking.
Here's one possible alternative to using bit-fields:
#include <stdio.h>
#define MASK_A 0x00FF
#define MASK_B 0x3F00
#define MASK_C 0xC000
#define SHIFT_A 0
#define SHIFT_B 8
#define SHIFT_C 14
unsigned GetField(unsigned all, unsigned mask, unsigned shift)
{
return (all & mask) >> shift;
}
unsigned SetField(unsigned all, unsigned mask, unsigned shift, unsigned value)
{
return (all & ~mask) | ((value << shift) & mask);
}
unsigned GetA(unsigned all)
{
return GetField(all, MASK_A, SHIFT_A);
}
unsigned SetA(unsigned all, unsigned value)
{
return SetField(all, MASK_A, SHIFT_A, value);
}
/* Similar functions for B and C here */
int main(void)
{
unsigned myABC = 0;
myABC = SetA(myABC, 3);
printf("%u", GetA(myABC)); // Prints 3
}
I know this is an old one, but I would like to add my thoughts.
Headers in C are meant to be usable across objects, which means the compiler has to be somewhat consistent.
In my experience I have always seen bitfields in LSB order. This will put the bits in MSB->LSB order of c:b:a
The 16 bits, read in byte order is "00 40". Translated from Little-endian, this is a 16-bit value of 0x4000.
This is:
c == [15:14] == b'01
b == [13:8] == 0
a == [7:0] == 0