11

C/C++ bitfields seem to have a lot of application in hardware drivers and binary network transfers. However they don't seem to be widely used and are generally discouraged, because the actual binary layout is implementation specific, as seen in this quote from the C99 standard 6.7.2.1/10 - "Structure and union specifiers";

An implementation may allocate any addressable storage unit large enough to hold a bitfield. 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.

My question is rather simple; Why did the committee decide to leave bit fields to be something implementation specific, and thereby making it a compiler construct, which can mainly be used for reduced memory usage, where's it could in many cases have been used to provide nice binary layouts, and free developers from bit-fiddling code?

Skeen
  • 4,614
  • 5
  • 41
  • 67
  • I can imagine some reasons... endianness springs to mind. But also, putting a bitfield partly in one and partly in another byte would have a _lot_ of performance impact, so that the committee decided compilers are free to choose how to do it, perhaps based on user prefs of speed or size optimisation. – Mr Lister Jul 18 '13 at 12:49
  • 2
    I'm sure the fact that the number of bits per byte doesn't have to be 8 has something to do with it as well. – Drew McGowen Jul 18 '13 at 12:50
  • @Mr Lister: As for ensuring that a field is aligned in the next byte, and therefore not starting in the middle of a byte, we're given the zero size bit field, right? - So that's already in the standard. – Skeen Jul 18 '13 at 12:55
  • @Mr Lister: As for endianness, it makes sense, however they could have added a specifier to force a specific endianness, and where leaving this out, would default to the machine endianness, this would not only solve issues for bit fields, but for transfering any multi byte data structure. – Skeen Jul 18 '13 at 12:58
  • @Skeen: The C++ Standard avoids "forcing" such specifics. Requiring big-endian would make bitfields suboptimal on all little-endian systems. – John Dibling Jul 18 '13 at 13:25
  • @John Dibling: I understand that, however why not have it possible to require a specific structure to be handled with a specific endianness as done with the CONVERT in FORTRAN. - such that by default it uses the standard endianness, but one can require a specific one. – Skeen Jul 18 '13 at 13:28
  • @Skeen: But then in order to effectively use a bitfield, you would need to know the endianness of the system you're on. Writing compliant cross-platform code now becomes a pain. – John Dibling Jul 18 '13 at 13:31
  • @John Sibling: What I was trying to suggest, is that if you leave out the endianness specifier, its left to the compiler, as the current behavior is. Much alike with the 'alignas' specifier. - You can force a behavior or leave it to the compiler. – Skeen Jul 18 '13 at 13:34
  • 1
    @Skeen: Right, and the standards committies default behavior in such cases is to leave it to the compiler. (Actually the hardware in this case) You can wring your hands and argue "why," but it's all just yelling at the rain. One of the fundamental characteristics of C++ as a language is that many of these kinds of decisions are left to the implementation. – John Dibling Jul 18 '13 at 13:38

1 Answers1

8

For the same reason so many other things are not strictly specified by the standard: To allow flexibility to produce a compliant compiler for a large number of platforms and systems, and still have an EFFICIENT compiler.

In particular, bitfields having to be stored in a particular bit/byte-order would make it horribly slow on machines whose natural byte-order is the "wrong way around".

Yes, it means that it's a right pain in the behind to make bitfields portable across multiple archiectures and platforms. If you really need that, then perhaps you should consider some other solution...

Mats Petersson
  • 126,704
  • 14
  • 140
  • 227
  • 1
    So, at least in my world, this means in order to avoid a possibly slow feature, they ended up with a mostly unusable feature? – Skeen Jul 18 '13 at 12:50
  • 2
    No, it's perfectly usable, as long as you don't ALSO require that it's perectly portable. Note that for many architectures, the main difference will be byte-order, not bit-order, so you are OK as long as the processor is the same. And I'm sure most people would complain at least as loudly if it wasn't efficient (but perfectly portable and well defined). – Mats Petersson Jul 18 '13 at 12:54
  • 1
    You're probably right, though I'd rather have a portable well defined bitfield, and then do the bit-fiddling myself, whenever I need performance.. Than the other way around. – Skeen Jul 18 '13 at 13:02
  • But then you can see it the other way around too - if you want strict byte-order and bit-order, you need to do bitfiddling yourself. If you want something that is reasonably quick and reasonably portable (remember it's only if you store binary values on one machine and restore the binary value on a different machine or similar things that cause problems - it will work just fine when you don't do this). – Mats Petersson Jul 18 '13 at 13:13
  • +1 - all good. As another illustrative complexity, a bit field that spans two words might require far more instructions or penalty clock-cycles on one CPU than another, leading to different attitudes to tight packing. – Tony Delroy Jul 18 '13 at 15:07
  • Mind you, it's been implementation-specific for 30+ years, and breaking about 100 billion lines of existing C code (conservative estimate) is NOT a good idea. – MSalters Jul 18 '13 at 23:43