I would like to know if there is a single bit structure in Rust. Not byte (8 bits), but a single bit (either 0, or 1). If yes, how can I use it?
The closest I've ever seen (whether in C or in Rust) is bitwise manipulations e.g. >>
, &
, |
etc.
But even those operate on the bits of a value that's at least 1 byte wide i.e. at least a u8
or i8
.
(update: as @mbrubeck points out below, the bool
type is very likely what you'll want to use if it's about a single bit, and otherwise use the crates listed in his post).
At this point I'm not certain that current CPUs would even support manipulating loose bits in their load
and store
instruction equivalents.
There's no primitive one-bit type. The closest thing is bool
, which conceptually represents a single bit, but physically it is represented as one byte in memory.
When you want to pack multiple one-bit values efficiently in memory (without using a full byte for each of them), you can use libraries like bitvec, bitflags, and packed_struct.
LLVM lets you define arbitrary-width integers so in theory Rust could have a single-bit value, but the smallest unit of memory modern processors can work with is the byte so in practice your single-bit value would take up 8 bits in memory.
C has a concept called the bitfield, but this is just syntactic sugar for bitwise manipulations.
It’s probably worth noting that, unlike some other languages with bool
types, Rust guarantees that a boolean value is either 0x01
or 0x00
, i.e. only the least-significant-bit is used, which potentially makes pretending that bool
is a single bit much safer in some expressions.
However, Rust does not guarantee that the other bits in the underlying u8
are unused, thus providing a 7-bit niche for rustc
's use. bool
and option(bool)
both encode in one byte, implying that the compiler is using those apparently-unused seven bits for other purposes.
Good point!
The compiler only uses those niche values when it is not actually a bool
though. So for Option<bool>
, you may see raw values for Some(false) = 0
, Some(true) = 1
, or None = 2
(not an exact guarantee). But if you're looking at a bool
alone, or say dereferencing &bool
, the whole byte will be only 0x00
or 0x01
.
Here there is some post about bitfields required for feature Rust as it is a system programming language: Rust Roadmap 2021: Allowing for arbitrary size integer primitives | The subconscious mumblings of therealprof
It looks true especially for embedded programming where most MCU mode & I/O registers are bit-splitted, so embedded Rust requires at least C-like packed structures.
Also, we have also the ux crate but starts from two bits integers.
For the specific case of memory-mapped registers, using b3
or such types is probably never going to work, because you cannot have a "&VolatileCell
" in Rust. The very concept is fundamentally broken and doesn't work. Use voladdress instead.
After you read or before you write the MMIO, though, yeah.
For regular memory, bitvec is wonderful. There's IIUC still a missing space for a "bitstruct" based off of bitvec and its techniques which, while not as integrated as a language addition would be, can still imho feel more integrated than other existing solutions.
An unsigned integer is kind of a bit-field. Testing for certain bits is easy [1, 2, 4, 8, ..] & int == 0, or > 0. See Bit Twiddling Hacks
This allows counting the number of single bits with one loop cycle per bit set to one. This can be used to isolate each bit set to one, and there is an easy test for exactly one bit set to one, (int - 1) & int == 0. There is an easy test for no bits set to one, == 0 All bits set to 1, == u8::MAX;
@Bitflogger, please note that u8::count_ones is significantly faster than a loop Think closer to 1-4 cycles, always, instead of 1 cycle per set bit.
I agree that library support should be able to take care of multi-bit field packed structs, and that should be explored more fully before we just make it part of the language because C did.
I did not know about that, Thanks!
This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.