Octocontrabass wrote:Ethin wrote:So define the struct as you guys indicated earlier, than use shifts and masks to extract (and set) those bits? Just confirming. So I might define the structure the same way but with all u8s?
If you're not going to be using it to interact with the hardware, then you can define the structure however you want. For example, you might leave out the reserved bits since you won't be able to interpret them anyway.
The important part is using packed bits when you interact with the hardware. How you pack and unpack the bits is up to you. (As others have noted, C bitfields are not the most portable way of doing it, since they are ABI-dependent. I still think they're a good way to visualize the structure though.)
I do want to use them to interact with the hardware, so I've defined them as all u8s (since I can't use bitfields, and I presume that if I use a complex structure like a bit vector the structure will read in and write out data that's beyond the bounds of the actual structure in HW memory). Bitfields are nice, though I'm kinda confused.... aren't they just a way of limiting the range of an integer? Like if you define a u8 that takes up 5 bits, its still going to take up the remaining bits, you just won't be able to access them?
Edit: Oh, I see now... the C standard says: "An implementation may allocate any addressable storage unit large enough to hold a bit-field. If enough space remains, a bit-field that immediately follows another bit-field in a structure shall be packed into adjacent bits of the same unit. If insufficient space remains, whether a bit-field that does not fit is put into the next unit or overlaps adjacent units is implementation-defined. The order of allocation of bit-fields within a unit (high-order to low-order or low-order to high-order) is implementation-defined. The alignment of the addressable storage unit is unspecified." I'm not really sure how I could accomplish such a thing in Rust, which is what I'm using... It doesn't support bitfields at the moment, and even if I use the packed representation I don't know how accurate that comes to bitfields. The Rustonomicon has this to say on the packed representation: "repr(packed) forces Rust to strip any padding, and only align the type to a byte. This may improve the memory footprint, but will likely have other negative side-effects.
In particular, most architectures strongly prefer values to be aligned. This may mean the unaligned loads are penalized (x86), or even fault (some ARM chips). For simple cases like directly loading or storing a packed field, the compiler might be able to paper over alignment issues with shifts and masks. However if you take a reference to a packed field, it's unlikely that the compiler will be able to emit code to avoid an unaligned load.
As of Rust 2018, this still can cause undefined behavior.
repr(packed) is not to be used lightly. Unless you have extreme requirements, this should not be used.
This repr is a modifier on repr(C) and repr(rust)."