Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

The tough thing about bitfields in C are their poor portability as they can get laid out differently in memory by platform and compiler. They're often avoided even in C when you're looking for a good degree of interoperation (e.g. structs used in networking or on-disk-formats, etc.).


The scary thing about bitfields is also that in the context where they make the most sense to use, writing bits to CPU registers, they are also the easiest to misuse as writing one bitfield requires both reading and writing the whole byte(minimum addressable unit), which can have unexpected effects when writing to registers. On some chips, reading registers can have different values than writing so the value you are writing the second time might cancel out what you wrote the first time, or that each write triggers something you only wanted to trigger once.

    myregister.tx_baudrate_bitfield = 1;  // Writes the whole myregister
    myregister.tx_now_bitfield = 1;   // Reads the whole myregister, then bitmasks and finally writes.
The same mistake can of course be done with manual masking also but then it's more obvious that you are reading the registers also. When the code looks like above it's very easy to not realize that it also requires a read.


Right. And we can't just say "we need bitfields", we need 100% C-compatible bitfields, for FFI.


But not very important for FFI, since bitfields rarely seem to show up in C APIs (presumably for exactly the reasons mentioned above).

A kind of similar issue appears even with enums, because it is hard to guess the size of the integer that a given enum is implemented with. This is why it some not to use C enums in public interfaces to libraries.


Gecko (and many other large C++ programs that care about memory usage of certain heap allocated types) uses bitfields often enough, and we've had to teach bindgen how to generate bitfields so that we can access them from Rust.


Were these intended as part of an external interface for Gecko? In which case I would say using bitfields (as opposed to explicit masks) was a mistake.

But yes, I can imagine that for Mozilla there is a need to mix Rust and C++ right inside an application at boundaries that are not usually considered external, in which case all kinds of non-portable C constructs are acceptable.


> A kind of similar issue appears even with enums, because it is hard to guess the size of the integer that a given enum is implemented with.

True; fortunately, Rust has a means of declaring the size of an enum, with #[repr(u8)] and similar. But you do have to figure out the size of the C enum.




Consider applying for YC's Summer 2026 batch! Applications are open till May 4

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: