Bit-Fields in C/C++: what is guaranteed, what is implementation-defined?

678 Views Asked by At

Reading https://en.cppreference.com/w/c/language/bit_field, are the following conclusions correct?

  • Adjacent bit-fields have no padding in between (this seems to be differentin 6.7.2.1 of the C-standard).
  • The placement of a bit-field within the storage-unit is implementation-defined.
  • The position of the bits inside a bit-field is implementation-defined.

(For C++ see also: Characteristics of bit-Fields in C++.)

1

There are 1 best solutions below

0
On BEST ANSWER

As a preliminary, there is no language "C/C++" such as is referenced by the question title. C and C++ are distinct languages sharing a common subset. In particular, C is not a subset of C++.

With regard to C, all the specifics the current language spec (C17 at this moment) provides about bitfield layout are in paragraphs 6.7.2.1/11-12.

are the following conclusions correct?

  • Adjacent bit-fields have no padding in between (this seems to be differentin 6.7.2.1 of the C-standard).

Bit fields are not laid out directly within a structure. The C implementation lays out "addressable storage units" for them within the structure, and lays out bitfields within those. The sizes and alignment requirements of the ASUs are unspecified.

The spec does say that if there is sufficient space in the ASU to which one bitfield is assigned, then an immediately-following bitfield is packed into adjacent bits of the same ASU. This means that there are not padding bits between those bitfields. However, if there is not sufficient space, then it is implementation-defined whether the immmediately-following bitfield spans two ASUs or whether all its bits are assigned to a separate one, leaving unused (padding) bits in the first. Additionally, a zero-width bitfield can be used to force the bitfield following it to be assigned to a new ASU, possibly requiring padding bits in a previous one.

Moreover, the spec has nothing to say about whether there are padding bytes between ASUs. ASUs are not required to be uniform in size or to have the same alignment requirements as each other, so it is plausible that padding bytes would sometimes be required between them even in an implementation that is not intentionally perverse in this regard.

  • The placement of a bit-field within the storage-unit is implementation-defined.

The spec explicitly says that the order of bitfields within an ASU is implementation defined. That's in the right-to-left vs left-to-right sense. "Order" is not exactly the same thing as "placement", but I guess that's what you mean.

  • The position of the bits inside a bit-field is implementation-defined.

Not really. This is a question of representation, not layout, and the relevant paragraphs of C17 are 6.2.6.1/3-4:

Values stored in unsigned bit-fields and objects of type unsigned char shall be represented using a pure binary notation.

[...] Values stored in bit-fields consist of m bits, where m is the size specified for the bit-field. The object representation is the set of m bits the bit-field comprises in the addressable storage unit holding it.

Footnote 49 clarifies the meaning of "pure binary notation" if you need that. All other details of bitfield representation are unspecified or undefined, not implementation-defined, which means that you cannot rely on them being documented.


Differences in C++ include, but are not necessarily limited to:

  • C++ officially sanctions more declared types for bit fields than does C.
  • C++ defines a mechanism for declaring bitfields that contain padding bits, but C does not.
  • Bitfield allocation and alignment are implementation defined in C++ (vs unspecified in C).

The relevant section of the C++ spec is [class-bit], 11.4.10 in the current draft spec.