C++ Logo

std-proposals

Advanced search

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

From: Frederick Virchanza Gotham <cauldwell.thomas_at_[hidden]>
Date: Wed, 20 Dec 2023 13:39:18 +0000
On Wed, Dec 20, 2023 at 12:35 PM Thiago Macieira wrote:
>
> I could conceive of a machine that automatically shifts the pointer addresses
> by the size of the datum being loaded or stored -- that is, the "pointers" are
> actually word counts from address 0 for the type in question. As I said, I've
> never heard of such machine, none such has been developed since the 1980s at
> least, and no one would develop such now because there's just too much code
> out there that assumes pointers are, indeed, interconvertible.


Well for the timebeing, the Standard says that 'void*' might have more
precision than 'long double*' and that the round trip might leave you
with a memory address that has its lower bits zeroed out. Maybe this
will change in C++26 or C++29.

We can keep the the microcontroller programmers, as well as the
supercomputer micro-optimisers, happy by adding three "if constexpr"'s
to the _Relocate function as follows:

    void _Relocate(void *const dst, void *const src)
    {
        using T = Monkey;
        using std::byte;

        std::memcpy(dst,src,__datasizeof(T));

        long double *pld;
        std::memcpy(&pld,src,sizeof pld);

        byte *p = static_cast<byte*>(static_cast<void*>(pld));

        if constexpr ( sizeof(byte*)!=sizeof(T*) ) p +=
alignment_modulus<T>(src);

        if ( p < static_cast<byte*>(src) ) return;
        if ( p >= (static_cast<byte*>(src) + __datasizeof(T))) return;

        // If control reaches here, we must adjust the pointer
        // but we must be careful because 'long double*' might
        // have less precision than 'byte*' (but it might not).
        // We will do this in three steps.

        // Step 1: Add the offset to 'p'
        p += static_cast<byte*>(dst) - static_cast<byte*>(src);

        // Step 2: Subtract the alignment modulus (if necessary)
        if constexpr ( sizeof(byte*)!=sizeof(T*) ) p -= alignment_modulus<T>(p);

        // Step 3: Convert to 'long double*' and store in (possibly
unaligned) destination
        if constexpr ( sizeof(byte*)!=sizeof(T*) ) assert( 0u ==
alignment_modulus<long double>(p) );
        pld = static_cast<long double*>(static_cast<void*>(p));
        std::memcpy(dst,&pld,sizeof pld);
    }

Tested and working: https://godbolt.org/z/qK736evY7

Received on 2023-12-20 13:39:09