0

When converting network data between big and little endian, it's my understanding that we swap all the bytes that make up the type. Regardless of the type's size, we swap them so that the first byte becomes the last byte, and the last byte becomes the first byte.
This can be expressed generically with the function below:

void SwapBytes(void *pv, size_t n)
{
    char *p = pv;
    size_t lo, hi;
    for(lo=0, hi=n-1; hi>lo; lo++, hi--)
    {
        char tmp=p[lo];
        p[lo] = p[hi];
        p[hi] = tmp;
    }
}

Without concern for efficiency,
I had hoped this would work on any data type-- including IEEE 754 doubles.


Then, I came across the following post,
where the user has swapped the bytes of a double in 4 byte chunks:

void send_double(double d) {
    long int i64 = *((reinterpret_cast<int *>)(&d)); /* Ugly, but works */
    int hiword = htonl(static_cast<int>(i64 >> 32));
    send(hiword);
    int loword = htonl(static_cast<int>(i64));
    send(loword);
}

double recv_double() {
    int hiword = ntohl(recv_int());
    int loword = ntohl(recv_int());
    long int i64 = (((static_cast<long int>) hiword) << 32) | loword;
    return *((reinterpret_cast<double *>(&i64));
}

Is there a special rule about this when it comes to network byte order?
At first, I thought it was about swapping 4 bytes at a time, regardless of the type, but that wouldn't make sense for uint16, where there are only 2 bytes.

What is the correct way to convert a IEEE 754 double into network byte order?
Do I flip all 8 bytes, or do I flip each half individually?

Community
  • 1
  • 1
Trevor Hickey
  • 36,288
  • 32
  • 162
  • 271
  • @M.M The code comes directly off another post. The main thing I wanted to point out, is that the user is attempting to flip the first 4 bytes of the double, followed by the last 4 bytes of the double, instead of flipping all 8 together. I want to know which is correct for network byte order. – Trevor Hickey Apr 27 '16 at 02:15
  • My advice would be to downvote that post and disregard its contents – M.M Apr 27 '16 at 02:16
  • @M.M Great. So the SwapBytes will work on shorts, ints, floats, doubles, long longs, etc? – Trevor Hickey Apr 27 '16 at 02:17
  • That would depend on what the sender did. You need to find out what specification the sender followed in sending the data; and if you are not writing portable code on your end (as it seems) then you have to match that specification to the endianness of the system you're coding for – M.M Apr 27 '16 at 02:22
  • Duplicate of this http://stackoverflow.com/questions/10616883/how-to-convert-double-between-host-and-network-byte-order ? – fghj Apr 27 '16 at 02:27
  • After `htonl` reverses (or no-ops, on big-endian systems) the byte order of each chunk, the high-order chunk is sent first, before the low-order chunk. So the 8-byte block is correctly transmitted with all bytes in correct network order, from most significant to least significant, independent of system endianness as well. Brilliant, however the code does brutally violate the strict aliasing rule and should not be used. – Christopher Oicles Apr 27 '16 at 04:17

1 Answers1

2

What is the correct way to convert a IEEE 754 double into network byte order?

As far as I can tell, there is no standard network byte order for IEEE754 doubles. Apparently people have rolled their own serialization.

The "network byte order" originally came about in the context of Internet Protocol, where it was common to send 32-bit values (IPv4 addresses) and 16-bit values (e.g. port number). The RFC 1700 originally defined the term, but that RFC is now obsoleted with no replacement.


For communication of a double, or any other data for that matter, both ends should agree on and follow a protocol specification. This will say how the double is encoded. The post you linked to, presumably followed a protocol which specified placing the IEEE754 64-bit format's bytes in the particular order that he showed. Other protocols may differ.

Community
  • 1
  • 1
M.M
  • 138,810
  • 21
  • 208
  • 365