C bitfields guarantees

Richard (Rikki) Andrew Cattermole richard at cattermole.co.nz
Fri Jul 5 21:25:41 UTC 2024


On 06/07/2024 9:12 AM, Steven Schveighoffer wrote:
> On Friday, 5 July 2024 at 19:56:49 UTC, Tim wrote:
>> On Friday, 5 July 2024 at 19:35:10 UTC, Steven Schveighoffer wrote:
>>>
>>> What if you need > 32 bits or want to pack into a `ulong`? Is the 
>>> behavior sane across compilers?
>>
>> The following struct has a different layout for different platforms:
> 
> ...
> 
> Thanks for this.
> 
> I also tested the following, and found it too shows discrepancies.
> 
> ```c
> struct S {
>      unsigned short x;
>      unsigned int a : 12;
>      unsigned int b : 12;
>      unsigned int c : 8;
> };
> ```
> 
> Here there are only `uint` bitfields, yet the compiler chooses to layout 
> the bits differently based on the *preceding* field.
> 
> Walter, I have to unfortunately withdraw my support for defining D 
> bitfields to just be the same as C bitfields -- the minefields are too 
> subtle. The statement that "If you use uint as the field type, you'll 
> get the same layout across every C compiler" is not true. And I don't 
> think we can really specify the true nature of what you must do for 
> portable bitfields in a way that is straightforward. Saying something 
> like "you can only use `uint` bitfields in structs that contain only 
> `uint` types" is not a good feature.
> 
> I'm back to requesting that we have a mechanism to request C bitfields 
> (such as marking a struct as `extern(C)`), or picking one C style and 
> going with that.
> 
> -Steve

I did not expect this.

This prevents my mitigation from working.

So now we also have to put it into an anonymous struct to even get the 
layout we think it should be.

```c
struct Foo {
      unsigned short x;

      struct {
         unsigned int a : 12;
         unsigned int b : 12;
         unsigned int c : 8;
      };

      //void* next;
};

int main() {
     struct Foo foo;
     foo.a = 1;
     foo.b = 0;

     return 0;
}
```

```asm
main:
  push   rbp
  mov    rbp,rsp
  mov    DWORD PTR [rbp-0x4],0x0
  mov    eax,DWORD PTR [rbp-0x8]
  and    eax,0xfffff000
  or     eax,0x1
  mov    DWORD PTR [rbp-0x8],eax
  mov    eax,DWORD PTR [rbp-0x8]
  and    eax,0xff000fff
  or     eax,0x0
  mov    DWORD PTR [rbp-0x8],eax
  xor    eax,eax
  pop    rbp
  ret
```


More information about the Digitalmars-d mailing list