Search code examples
c++visual-studio-2008endianness

How to byteswap a double?


I'm trying to write a byteswap routine for a C++ program running on Win XP. I'm compiling with Visual Studio 2008. This is what I've come up with:

int byteswap(int v) // This is good
{
    return _byteswap_ulong(v);
}

double byteswap(double v) // This doesn't work for some values
{
    union { // This trick is first used in Quake2 source I believe :D
        __int64 i;
        double  d;
    } conv;
    conv.d = v;
    conv.i = _byteswap_uint64(conv.i);
    return conv.d;
}

And a function to test:

void testit() {
    double  a, b, c;
    CString str;

    for (a = -100; a < 100; a += 0.01) {
        b = byteswap(a);
        c = byteswap(b);
        if (a != c) {
            str.Format("%15.15f %15.15f %15.15f", a, c, a - c);
        }
    }
}

Getting these numbers not matching:

-76.789999999988126 -76.790000000017230 0.000000000029104  
-30.499999999987718 -30.499999999994994 0.000000000007276  
 41.790000000014508  41.790000000029060 -0.000000000014552  
 90.330000000023560  90.330000000052664 -0.000000000029104

This is after having read through:
How do I convert between big-endian and little-endian values in C++?
Little Endian - Big Endian Problem
You can't use << and >> on double, by the way (unless I'm mistaken?)


Solution

  • Try 3

    Okay, found out there's a better way. The other way you have to worry about the order you pack/unpack stuff. This way you don't:

    // int and float
    static void swap4(void *v)
    {
        char    in[4], out[4];
        memcpy(in, v, 4);
        out[0] = in[3];
        out[1] = in[2];
        out[2] = in[1];
        out[3] = in[0];
        memcpy(v, out, 4);
    }
    
    // double
    static void swap8(void *v)
    {
        char    in[8], out[8];
        memcpy(in, v, 8);
        out[0] = in[7];
        out[1] = in[6];
        out[2] = in[5];
        out[3] = in[4];
        out[4] = in[3];
        out[5] = in[2];
        out[6] = in[1];
        out[7] = in[0];
        memcpy(v, out, 8);
    }
    
    typedef struct
    {
        int theint;
        float   thefloat;
        double  thedouble;
    } mystruct;
    
    
    static void swap_mystruct(void *buf)
    {
        mystruct    *ps = (mystruct *) buf;
        swap4(&ps->theint);
        swap4(&ps->thefloat);
        swap8(&ps->thedouble);
    }    
    

    Send:

        char    buf[sizeof (mystruct)];
        memcpy(buf, &s, sizeof (mystruct));
        swap_mystruct(buf);
    

    Recv:

        mystruct    s;
        swap_mystruct(buf);
        memcpy(&s, buf, sizeof (mystruct));