0

In VStudio 2010, I'm trying to create a union to access a 2-byte value conveniently:

#pragma pack(push,1) // disable padding
typedef struct {
    uint8_t r:3;
    uint8_t g:3;
    uint8_t b:3;
}tsRgb;

typedef union {
    uint16_t raw;
    tsRgb rgb; 
}tPixelData;
#pragma pack(pop)

int main(){
    tPixelData pixel;
    pixel.raw = 0xABE5;
    return 0;
}

I'm expecting to see pixel.r = 5, pixel.g = 4, pixel.b = 7. the r and g are ok, but the b is 3.

What am I doing wrong? I assume I'm not alligning the bits correctly?

Mihai Galos
  • 1,707
  • 1
  • 19
  • 38

2 Answers2

4

The third field will be in a separate byte.

In VC++ the bitfields do not cross the boundaries of the underlying type. When you have used 3+3 bits there are only 2 left, so the next field will use 3 bits from a fresh byte.

It might work better if you use uint16_t instead of uint8_t.

"Disable padding" works on the byte level, not on the bit level.

Bo Persson
  • 90,663
  • 31
  • 146
  • 203
  • *The bitfields do not cross the boundaries of the underlying type* That is implementation-defined. While they may not cross boundaries in the VStudio implementation the OP is using, bit-fields very well can cross the boundaries of the underlying storage units. Bit-fields are *extremely* implementation-dependent and *extremely* non-portable. – Andrew Henle Jan 05 '17 at 11:14
  • 1
    @Andrew - Ok, I added a clarification that the answer is for the system the OP is using. – Bo Persson Jan 05 '17 at 11:18
3

Using bit-fields is as you want to is fundamentally problematic. Per the C Standard, 6.7.2.1 Structure and union specifiers, paragraph 11 (since your question is also tagged C):

An implementation may allocate any addressable storage unit large enough to hold a bit- field. If enough space remains, a bit-field that immediately follows another bit-field in a structure shall be packed into adjacent bits of the same unit. If insufficient space remains, whether a bit-field that does not fit is put into the next unit or overlaps adjacent units is implementation-defined. The order of allocation of bit-fields within a unit (high-order to low-order or low-order to high-order) is implementation-defined. The alignment of the addressable storage unit is unspecified.

The layout and alignment of the bits in a bit-field are all implementation-defined. Fields may or may not cross storage unit boundaries, they may be stored in any order.

They're not portable at all.

Community
  • 1
  • 1
Andrew Henle
  • 32,625
  • 3
  • 24
  • 56
  • They are not a portable way of matching some on-the-wire bit format. They *are* a portable way of reducing the memory consumption of a struct (and that is all they should be used for.) – Martin Bonner supports Monica Jan 05 '17 at 11:36