C++ Logo

std-proposals

Advanced search

Re: [std-proposals] [[packed]]

From: Gašper Ažman <gasper.azman_at_[hidden]>
Date: Wed, 6 Dec 2023 16:52:29 +0000
++ for unaligned<trivial>

On Wed, Dec 6, 2023, 15:28 Lénárd Szolnoki via Std-Proposals <
std-proposals_at_[hidden]> wrote:

> packed is cursed, please no. I would much rather see
> std::unaligned<Trivial>.
>
> On 6 December 2023 00:44:50 GMT, Frederick Virchanza Gotham via
> Std-Proposals <std-proposals_at_[hidden]> wrote:
>>
>> There has been talk lately on the mailing list here of tail padding in
>> structs, and whether it can be either eradicated, or used for
>> overlapping objects.
>>
>> Consider the following code:
>>
>> struct Monkey {
>> long double a;
>> int b;
>> } __attribute__((packed));
>>
>> struct Donkey {
>> long double a;
>> int b;
>> };
>>
>> int main(void)
>> {
>> static_assert( sizeof(Monkey) != sizeof(Donkey) );
>>
>> Monkey m;
>>
>> m.b = 6;
>>
>> int *p = &m.b;
>>
>> *p = 7;
>> }
>>
>> When this program is compiled with GNU g++ or LLVM clang++, it gives
>> the following diagnostic:
>>
>> warning: taking address of packed member 'b' of class
>> or structure 'Monkey' may result in an unaligned pointer
>> value [-Waddress-of-packed-member]
>>
>> I was thinking . . . If [[packed]] were ever to be standardised, then
>> a 'packed struct' could behave as follows:
>> (Rule 1) Assignment is achieved by 'memcpy'. For example the line "m.b
>> = 6;" in the above snippet would become:
>> int const six = 6;
>> memcpy( &m.b, &six, sizeof m.b );
>> (Rule 2) When taking the address of any member of a packed struct, you
>> get a 'void*', for example:
>> int *p = &m.b; /* fails to compile */
>> void *p = &m.b; /* compiles okay */
>> (Rule 3) You cannot bind a reference to any member of a packed struct:
>> int &b = m.b; /* fails to compile */
>>
>> Of course you can get around Rule 2 and Rule 3 by using 'static_cast',
>> for example:
>> int *p = static_cast<int*>(&m.b);
>> int &b = *static_cast<int*>(&m.b);
>> but you only have to glance at these two lines to see that alignment
>> might be an issue.
>>
>> An alternative to Rule No. 2 would be that you can't take the address
>> of any member of a packed struct -- instead you must use
>> 'std::addressof_packed', so:
>>
>> int *p = &m.b; /* fails to compile */
>> void *p = &m.b; /* fails to compile */
>> int *p = std::addressof_packed(m.b); /* fails to compile */
>> void *p = std::addressof_packed(m.b); /* compiles okay */
>>
>> Furthermore . . . maybe we can create a new type, a 'packed struct',
>> from an already-defined 'unpacked struct'. So let's say we start out
>> with:
>>
>> struct Donkey {
>> long double a;
>> int b;
>> };
>>
>> And then later we do:
>>
>> typedef Donkey [[packed]] Monkey;
>>
>> or alternatively:
>>
>> using Monkey = [[packed]] Donkey;
>> --
>> Std-Proposals mailing list
>> Std-Proposals_at_[hidden]
>> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>>
>> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>

Received on 2023-12-06 16:52:41