C bitfields guarantees

Steven Schveighoffer schveiguy at gmail.com
Tue Jul 9 02:44:08 UTC 2024


On Tuesday, 9 July 2024 at 00:29:20 UTC, Walter Bright wrote:
> On 7/7/2024 8:49 AM, Steven Schveighoffer wrote:
>> Simple, no. Predictable, yes (it's unambiguous). And not 
>> obvious.
>
> It is trivially obvious to the most casual observer!
>
> Joking aside, it's the same technique used to inure a struct 
> layout against member alignment issues.

Yes, but there is a subtle difference -- the compiler ignores its 
own rules. In other words, explicit padding is required way more 
than with normal fields, which have consistent layout 
expectations.

As Timon points out, the compiler doesn't obey its own alignment 
requirements for bitfields.

>> What I want is for the compiler to *require* you to do this to 
>> avoid inconsistencies. It is going to be a mystery to anyone 
>> reading it *why* they put these things in there.
>
> I've seen fields named "pad" or "padding" many times in C code. 
> It's normal practice. Failing that, the purpose of comments is 
> to add the 'why'. One could also use `static assert` for extra 
> insurance.
>
> I've also seen fields named "reserved". No comment needed.

I concede that this is probably true. This does rely on 
convention though, and having the compiler yell at you if you try 
to remove it is even better.

>> To give some examples, we require empty if statements to use 
>> {} and not ;. It doesn't require any new syntax but it helps 
>> you avoid issues that many people make, even though it is 
>> allowed in C.
>
> Then one could not write a C compatible bitfield.

Yes you can. You can use C to write a C compatible bitfield 
(ImportC is a thing).

If you are using C bitfields as part of an API, it's either to do 
register layout or protocol processing. In both of these cases, 
layout matters more than arbitrary implementation matching.

If you have a use case that relies on the arbitrariness of C 
bitfields (i.e. doesn't care), then yeah, I guess you have to go 
through ImportC. I don't see a problem with this -- this is 
almost always not public API (due to the problems with C 
bitfields). See for instance how the linux kernel doesn't use 
bitfields for anything other than internal flags to save space.

It's not something we need to cater to.

>> We require explicit conversion when narrowing the range of an 
>> integer (i.e. assigning a long to an int). This avoids issues 
>> that many people would make, even though it is allowed in C.
>
> The C semantics are still allowed by adding a cast.

The C bitfield layout is achievable with D as well, it just might 
be the same exact syntax. i.e. you may need to use a uint instead 
of unsigned long long, or you might need to insert padding.

>
> Let's say Bob (poor Bob) needs to convert 20,000 lines of C 
> code to D. I know you've done some of this yourself! Bob 
> doesn't want to go through it line by line. Isn't it nice for 
> Bob if it "just works"? If all those data declarations just 
> work? Especially if the result still has to be compatible with 
> the files that C code wrote out?

ImportC is a thing. Leave the bitfield structs defined in C until 
you are fully in D, then use D bitfields.

Or you modify your C code to use the recommended layouts that D 
uses. If you don't care about layout, it shouldn't be a problem. 
And the D port should tell you exactly which parts you need to 
change through the errors.

> But what if the compiler says "Bob, you can't lay out a 
> bitfield like that!" Or worse, it lays out the bitfield into a 
> portable (but different) layout. Then it doesn't just work, Bob 
> has got some debugging to do (while Bob curses D and me), and 
> Bob's got to figure out an alternative. Who wants to do that? 
> Not Bob. Not me. Not nobody not nohow.

This already happens, we don't need bitfields for this kind of 
pain. ImportC is the solution.

Note that this follows the rule "if it looks like C and compiles, 
it should act like C". It's OK for things *not* to compile 
because we decided they are too error prone.

>> I'm not asking for any new features.
>
> Every switch that changes the semantics is a new feature and a 
> new source of complexity and bugs.
>
> One of my original requirements for D was no switches that 
> change language semantics. I have failed at that. But I wasn't 
> wrong to aspire towards it.

How convenient that we draw the line here.

I have no rebuttal for this as it's totally arbitrary, so if this 
is your only qualm, I guess you got me.

-Steve


More information about the Digitalmars-d mailing list