C bitfields guarantees
Steven Schveighoffer
schveiguy at gmail.com
Sat Jul 6 03:23:20 UTC 2024
On Saturday, 6 July 2024 at 00:16:23 UTC, Walter Bright wrote:
> On 7/5/2024 2:12 PM, Steven Schveighoffer wrote:
>> 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;
>> };
>> ```
>
> 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`.
> It's actually based on the *alignment* of the preceding field.
> I'm regret not saying that, but that's what I meant with the
> fields need to be of the same type, so they have the same
> alignment. If the uint bitfield started off aligned at a uint
> boundary, my statement holds.
Hm..., well it's not ideal to require the user to nudge the
compiler for the desired layout. It's an odd thing to say that a
uint bitfield may not be uint aligned, even if the equivalent
uint value would be.
The documentation note we talked about was simple -- just always
use the same type for your bitfields and it works. This is
different. Not impossible to learn, but for sure more challenging.
>
> When mixing field types of different sizes, there will be
> different alignments of those fields on different
> platforms/compilers, whether or not bitfields are involved.
>
The confusing thing here is that the alignment does *not* obey
the alignment of the containing type. And how it is aligned
depends instead on the *previous* member (sometimes). This is not
the case for full-sized uints.
I will note that I'm reading that ulong is aligned to 4-bytes on
32-bit linux, and so this does make an alignment difference even
for non-bitfields.
My recommendation still is either:
1. Denote D bitfields by a specified layout system (pick the most
common C one and do that). C bitfields can match the C compiler.
2. Simply forbid problematic alignments at compile time:
```d
struct S {
uint x;
uint64 a : 24;
uint64 b : 24;
uint64 c : 16;
}
// error, alignment of bitfield `a` may not match C layout,
please use padding or aligned bitfields to specify intended
layout.
// these are OK.
struct SWithPadding {
uint x;
uint _; // padding
uint64 a : 24;
uint64 b : 24;
uint64 c : 16;
}
struct SPacked {
uint64 x : 32;
uint64 a : 24;
uint64 b : 24;
uint64 c : 16;
}
```
Maybe the error only occurs if you specify a compiler switch?
-Steve
More information about the Digitalmars-d
mailing list