C++ Logo

sg12

Advanced search

Re: [ub] Type punning to avoid copying

From: Howard Hinnant <howard.hinnant_at_[hidden]>
Date: Fri, 26 Jul 2013 14:48:45 -0400
On Jul 26, 2013, at 2:35 PM, Jeffrey Yasskin <jyasskin_at_[hidden]> wrote:

> Howard, if Gaby's right that new(&memory) int; leaves the object with
> indeterminate value even if 'memory' started with a defined value (and
> I think he is), then that's the rule you're breaking when you
> explicitly change the active member of your union and then read the
> new member.

Ok, what if I change the active member this way:

float InverseSquareRoot4(float x)
{
    union U
    {
        float as_float;
        int32_t as_int;
    };
    
    U u = {x};
    // current member is as_float
    size_t active_member = 0;
    // temporary buffer
    alignas(U) char tmp[sizeof(U)];
    float xhalf = 0.5f*x;
    // Prepare to read from as_int
    if (active_member != 1)
    {
        std::memcpy(tmp, &u.as_float, sizeof(U));
        std::memcpy(&u.as_int, tmp, sizeof(U));
        active_member = 1;
    }
    // current member is as_int
    u.as_int = 0x5f3759df - (u.as_int>>1);
    // Prepare to read from as_float
    if (active_member != 0)
    {
        std::memcpy(tmp, &u.as_int, sizeof(U));
        std::memcpy(&u.as_float, tmp, sizeof(U));
        active_member = 0;
    }
    // current member is as_float
    u.as_float = u.as_float*(1.5f - xhalf*u.as_float*u.as_float);
    return u.as_float;
}

Howard

Received on 2013-07-26 20:48:41