1

If I have 16 bits that represent 3 pairs of values, each 5 bits long, and one other 1 bit value, in exactly this order, is it safe to use a bitfield to describe this? Does ANSI C guarantee that the bits will be exactly in the order that I specify?

struct {
    unsigned v1 : 5;
    unsigned v2 : 5;
    unsigned v3 : 5;
    unsigned v4 : 1;
} test;

If not, is there any other data structure that I can use to represent this? Or should I just store two 8 bit chars and manipulate them programmatically to be assured of portability?

Thomas Dickey
  • 51,086
  • 7
  • 70
  • 105
rid
  • 61,078
  • 31
  • 152
  • 193

3 Answers3

4

The relevant quote I could find is 6.7.2.1(1), from C99:

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.

I think that the unsigned isn't actually the "underlying unit" type, but rather, it's only a part of the bitfield declaration itself: T : n means "take n bits of type T". The real question is whether the implementation is required to pick a "large" unit. For example, it could use three bytes by making the unit a char; one for v1, one for v2, and the last one for v3, v4. Or it could make the unit a 16-bit integer, in which case it would be required to use only one single unit.

As you noted, though, the ordering of the bit fields within the unit is unspecified. The atomic unit of data in C is an address, and bitfields don't have addresses. It's guaranteed that the address of struct members increases in order of their declaration, but you cannot make such a statement about bitfields (only about their underlying units).

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
  • Hrm, that doesn't specify exactly how the bits are to be ordered. – rid Jun 05 '12 at 02:40
  • @Radu: You're right. I expanded the quote, and I guess the answer is "implementation-defined". – Kerrek SB Jun 05 '12 at 02:46
  • I see... So the implementation might use any number of bytes to store the values, and each sequence of 5 bits could be anywhere, before or after any other sequence, and even the bits in the sequence are not guaranteed to be in any order whatsoever... – rid Jun 05 '12 at 02:52
1

You could use the uint16_t type from stdint.h, which is guaranteed to be a type synonym for an unsigned 16-bit quantity. If you're concerned about endianness, it gets more complicated.

Greg E.
  • 2,722
  • 1
  • 16
  • 22
  • So the bits are not guaranteed to be in the order I specify, therefore I should manipulate the data manually? – rid Jun 05 '12 at 02:37
  • Yes, if you want to try to pack all the information into a single bitset represented by one variable, you cannot be assured of whether the endianness of the system is the same as that intended by your code. I'm also not aware of any truly portable way of determining the endianness of a system at compile time, although different methods of varying reliability do exist. – Greg E. Jun 05 '12 at 02:40
0

In addition to the implementation-defined aspects of bit fields, you might also need to add a pragma or other compiler directive to tell the compiler not to insert any padding bits.

Here is an answer I just wrote about how to use bit fields to extract some bits from a byte value. When I wrote this, I found I needed to add #pragma pack(1) or else my bit fields didn't fit into a single byte.

Access bits in a char in C

This answer also shows how to use a union to let you access the data as a complete byte or as bit fields. You could use the same technique to access the data as either a short integer or as bit fields.

Community
  • 1
  • 1
steveha
  • 74,789
  • 21
  • 92
  • 117