Why are non-const references to bitfields prohibited?

前端 未结 2 600
梦如初夏
梦如初夏 2021-01-02 04:09

Section 9.6/3 in C++11 is unusually clear: \"A non-const reference shall not be bound to a bit-field.\" What is the motivation behind this prohibition?

I understand

相关标签:
2条回答
  • 2021-01-02 04:53

    You can’t take a non-const reference to a bitfield for the same reason you can’t take its address with &: its actual address is not necessarily aligned to char, which is definitionally the smallest addressable unit of memory in the C++ abstract machine. You can take a const reference to it because the compiler is free to copy the value, as it won’t be mutated.

    Consider the issue of separate compilation. A function taking a const uint32_t& needs to use the same code to operate on any const uint32_t&. If different write behaviour is required for ordinary values and bitfield values, then the type doesn’t encode enough information for the function to work correctly on both.

    0 讨论(0)
  • 2021-01-02 04:57

    Non-const references can't be bound to bit-fields for the same reason pointers can't point to bit-fields.

    While it is not specified whether references occupy storage, it is clear that in non-trivial cases they are implemented as pointers in disguise, and this implementation of references is "intended" by the authors of the language. And just like pointers, references have to point to an addressable storage unit. It is impossible to bind a non-const reference to a storage unit that is not addressable. Since non-const references require direct binding, a non-const reference cannot be bound to a bit-field.

    The only way to produce a pointer/reference that can point to bit-fields would be to implement some sort of "superpointer" that in addition to the actual address in storage would also contain some sort of bit-offset and bit-width information, in order to tell the writing code which bits to modify. Note that this additional information would have to be present in all data pointer types, since there's no such type in C++ as "pointer/reference to bit-field". This is basically equivalent to implementing a higher-level storage addressing model, quite detached from the addressing model provided by the underlying OS/hardware platform. C++ language never intended to require that sort of abstraction from the underlying platform out of pure efficiency considerations.

    One viable approach would be to introduce a separate category of pointers/references such as "pointer/reference to bit-field", which would have a more complicated inner structure than an ordinary data pointer/reference. Such types would be convertible from ordinary data pointer/reference types, but not the other way around. But it doesn't seem to be worth it.

    In practical cases, when I have to deal with data packed into bits and sequences of bits, I often prefer to implement bit-fields manually and avoid language-level bit-fields. The name of bit-field is a compile-time entity with no possibility of run-time selection of any kind. When run-time selection is necessary, a better approach is to declare an ordinary uint32_t data field and manage the individual bits and groups of bits inside it manually. The run-time selection of such manual "bit-field" is easily implemented through masks and shifts (both can be run-time values). Basically, this is close to manual implementation of the aforementioned "superpointers".

    0 讨论(0)
提交回复
热议问题