C bitfields guarantees

Steven Schveighoffer schveiguy at gmail.com
Sun Jul 7 03:50:10 UTC 2024


On Saturday, 6 July 2024 at 23:26:43 UTC, Walter Bright wrote:
> On 7/5/2024 8:23 PM, Steven Schveighoffer wrote:
>> On Saturday, 6 July 2024 at 00:16:23 UTC, Walter Bright wrote:
>>> The following will also show discrepancies:
>>>
>>> ```
>>> struct T {
>>>     unsigned short x;
>>>     unsigned int y;
>>> }
>>> ```
>>>
>>> for the same reason.
>> 
>> I tested this struct, and there were no discrepancies between 
>> compilers. All compilers put 2 bytes of padding between the 
>> `ushort` and the `uint`.
>
> Try it with a 16 bit compiler, which aligns on 16 bits rather 
> than 32 bits.
>
> No, I'm not cheating with this - I wanted to point out the 
> consistency between 32 bit compilers, despite the Standard 
> saying nothing about it. But I can still break the example, 
> with a 32/64 bit compiler:
>
> ```
> struct U {
>     unsigned int x;
>     unsigned long y;
> }
> ```
>
> You'll get different sizes for 32 vs 64 bit compilations, 
> including with D.

Right, but with bitfields, you get discrepancies within the *same 
compiler*.

Let's take another example:

```c
struct U {
   unsigned int x;
   unsigned long long y: 30;
   unsigned long long z: 34;
}

struct U2 {
   unsigned int x;
   unsigned long long y: 34;
   unsigned long long z: 30;
}
```

In the first case, Linux 64-bit clang will layout y to be right 
after x, and z will be pushed 2 bits further so it lines up on a 
64-bit address.

In the second case, in the same compiler, y is pushed *32* bits 
off so it lines up on a 64-bit address space, and z is past that.

In both cases, 96 bits of data consumes 128 bits (sizeof both 
structs is 16).

In other words, the compiler makes probably unexpected layout 
decisions, and the reason is "because C does it".

Truly, with C, you cannot count on *any* explicit layout. Yes, 
there are reasons, and all of those have to do with performance. 
But when the goal is explicit layouts, then confusion rules.

This is why I said, either define what D does explicitly, or warn 
when it does something really bizarre for the sake of C.

Another option is just to say, "don't use bitfields for anything 
other than space-saving. Do not attempt to use bitfields for 
defined bit layout, because the compiler can make arbitrary 
decisions on layout." But you will have to tell [this 
guy](https://forum.dlang.org/post/v622m1$mu4$1@digitalmars.com).

D has a chance to do better, but it's clear we are just going to 
saddle ourselves with C insanity for the sake of zero real use 
cases.

-Steve


More information about the Digitalmars-d mailing list