Bit fields: Proposal

So what to do, what to do?

This is the seventh and last post of my Bit fields series; describing how to not use bit fields, how to use them, the limitations imposed by architecture and the compiler’s implementation, the use of volatile, and finally a show-stopper as well as this proposal to fix it.


Overview

This proposal allows the (optional) definition of what value the compiler should write to a bit field when the bit field is not being explicitly written. If a value is being explicitly written, then obviously that value should be used regardless of the definition. But when a different field is being updated, if a value is defined for this field then rather than using the value read, the defined value should be used instead.

Example

In the final example from the show-stopper post, I described a common real-world mechanism called the “read, write 1 to clear” bit field (rw1c or rc_w1), followed by a contrived specification. Using that as a base, the below proposed construct will allow even rw1c fields to be included in struct bit fields.

// Interrupt Status Register
struct ISR {
   bool     a : 1 default 0;     // Interrupt cause 'a' [rw1c]
   bool     b : 1 default 0;     // Interrupt cause 'b' [rw1c]
   unsigned   : 3 default 0b101; // Reserved (1s used for demonstration)
   bool     c : 1 default 0;     // Interrupt cause 'c' [rw1c]
   unsigned   : 0;               // Pad out to full width (could use default)
}; // ISR

Note that the above proposed syntax is less important than the concept. Obviously the = operator is unavailable, since that is used to define an initialisation value. But whether the reserved word default is used, or perhaps the == operator, or whatever else others may suggest, the idea is that the compiler can be signalled what value to write for default fields.

Architecture

If the struct bit field is larger than the data size written by the target architecture, then only the fields that will be affected by the target write need to have their possible default value incorporated. Indeed, if the architecture permits bit writes, then no other fields would need to be written at all. Note carefully though: a bit-insert-to-memory assembly mnemonic (e.g. the short-lived x86 IBTS mnemonic) would NOT be a true bit access; it would perforce be a read-modify-write instruction.

Efficiencies

Note that if all of the (to-be-written) fields of a structure have a default, then the compiler doesn’t need to perform a read-modify-write operation for any write: it can simply combine the written value with the other given values and perform a single complete write.

Exceptions

Seemingly paradoxically, there shouldn’t be any exceptions. Any bit field should be able to have a definition applied, simply because the compiler will be writing to that field while updating another target field. So whether a field is const, or anonymous, or even a padding field with : 0, the definition should be allowed. In particular, note that the latter will override the current language rule that anonymous and padding fields should always be written as 0, as demonstrated above.

In Conclusion

struct bit fields do not seem to be used very often in code. They’ve been around since the language began, but many programmers insist on using explicit definitions and code instead—either through ignorance or dissatisfaction with what bit fields offer.

Perhaps with stronger assertions about how bit fields are implemented, along with the above extension proposal,  programmers will feel more confident in using them.


Comments are welcome. I suggest that generic comments on the whole “Bit fields” series and concepts go on the main page, while comments specific to this sub-page are written here.

Leave a comment