12

I've come across many comments on various questions regarding bitfields asserting that bitfields are non-portable, but I've never been able to find a source explaining precisely why.

At face value, I would have presumed all bitfields merely compile to variations of the same bitshifting code, but evidently there must be more too it than that or there would not be such vehement dislike for them.

So my question is what is it that makes bitfields non-portable?

Pharap
  • 3,826
  • 5
  • 37
  • 51
  • 1
    In what context were they called "unsafe"? Add a link? – anatolyg Jul 05 '16 at 07:22
  • 6
    I think it's mostly how people abuse bitfields to extract pieces of other data types' representations at sub-byte levels, which is completely non-portable. – user2357112 Jul 05 '16 at 07:22
  • @anatolyg [Lundin's comment](http://stackoverflow.com/questions/35934375/bitfields-in-c-programming-language/35935493#comment59526628_35934375) on [this question](http://stackoverflow.com/questions/35934375/bitfields-in-c-programming-language/35935493). Granted I haven't seen them being accused of being 'unsafe' as much as I have 'non-portable', but still. – Pharap Jul 05 '16 at 07:29
  • 1
    Related: http://stackoverflow.com/a/31727805/1377706 – Pharap Jul 05 '16 at 07:32
  • 1
    `non-portable` - Big Endian compilers tend to arrange them in opposite manner to Little Endian compilers. Oh, I now see you've mentioned that as part of your question, so - yes, I have personally encountered that (not sure what the language standard says about it, so I guess that it simply doesn't). – barak manos Jul 05 '16 at 07:33
  • 4
    Of course, if you're using bitfields for their safe use cases, big/little bitfield layout doesn't matter any more than big/little integer layout. People seem a lot more interested in the unsafe use cases, though. – user2357112 Jul 05 '16 at 07:40
  • 5
    Used correctly, bit fields are safe and portable. You can misuse bit fields and create non-portable code but that's no different from misusing ints, pointers, etc. – Support Ukraine Jul 05 '16 at 07:54

2 Answers2

16

Bit fields are non-portable in the same sense as integers are non-portable. You can use integers to write a portable program, but you cannot expect to send a binary representation of int as is to a remote machine and expect it to interpret the data correctly.

This is because 1. word lengths of processors differ, and because of that, the sizes of integer types differ (1.1 byte length can differ too, but that is these days rare outside embedded systems). And because 2. the byte endianness differs across processors.

These problems are easy to overcome. Native endianness can be easily converted to agreed upon endianness (big endian is de facto standard for network communication), and the size can be inspected at compile time and fixed length integer types are available these days. Therefore integers can be used to communicate across network, as long as these details are taken care of.

Bit fields build upon regular integer types, so they have the same problems with endianness and integer sizes. But they have even more implementation specified behaviour.

  • Everything about the actual allocation details of bit fields within the class object

    • For example, on some platforms, bit fields don't straddle bytes, on others they do
    • Also, on some platforms, bit fields are packed left-to-right, on others right-to-left
  • Whether char, short, int, long, and long long bit fields are signed or unsigned (when not declared so explicitly).

Unlike endianness, it is not trivial to convert "everything about the actual allocation details" to a canonical form.

Also, while endianness is cpu architecture specific, the bit field details are specific to the compiler implementer. So, bit fields are not portable for communication even between separate processes within the same computer, unless we can guarantee that they were compiled using the same (or binary compatible) compiler.


TL;DR bit fields are not a portable way to communicate between computers. Integers aren't either, but their non-portability is easy to work around.

eerorika
  • 232,697
  • 12
  • 197
  • 326
4

Bit fields are non-portable in the sense that the ordering of the bit is unspecified. So the bit at index 0 with one compiler could very well be the last bit with another compiler.

This prevents the use of bit fields in applications like toggling bits in memory-mapped hardware registers.

But, you will see hardware vendor use bitfields in the code they release (like microchip for instance). Usually, it's because they also release the compiler with it or target a single compiler. In microchip case for instance, the licence for their source code mandates you to use their own compiler (for 8 bits low-end devices)

The link pointed to by @Pharap contains an extract of the (c++14) norm related to this un-specified ordering: is-there-a-portable-alternative-to-c-bitfields

jww
  • 97,681
  • 90
  • 411
  • 885
fjardon
  • 7,921
  • 22
  • 31
  • 2
    That bit field layout is implementation-defined does *not* make bit fields non-portable. It is the code assuming a specific layout which is non-portable. – Support Ukraine Jul 05 '16 at 08:36
  • @4386427: The general *reason* for using bit fields is to get a desired layout, e.g. option bits in an argument to an OS API function. The problem is that not all compilers may produce the same result (or put another way, that the standard doesn't offer reasonable guarantees for the most common use case). At the end, someone's screwed, but not necessarily the original programmer. – Cheers and hth. - Alf Jul 05 '16 at 08:39
  • @4386427 A language construct is not portable or not portable. It is supported or not by a compiler. When talking about portability we always talk about the *use* of these constructs. I didn't think it was necessary to precise that. – fjardon Jul 05 '16 at 08:41
  • @fjardon - Agree - to the first part of your comment. And that's the whole problem with this question. The question (and the first part of your answer) indicates that bit fields can't be used in a fully portable way - something which is of cause wrong. The fact that bit fields often are used get a specific layout on a specific system/compiler doesn't make bit fields non-portable in general. There are use case for bit fields which can written 100% portable. Something worth mentioning, IMO. – Support Ukraine Jul 05 '16 at 09:29