How to manage endianess of double from network

前端 未结 3 1948
迷失自我
迷失自我 2020-12-18 09:32

I have a BIG problem with the answer to this question Swap bits in c++ for a double

Yet, this question is more or less what I search for: I receive a double from th

相关标签:
3条回答
  • 2020-12-18 09:34

    I could not make John Källén code work on my machine. Moreover, it might be more useful to convert the double into bytes (8 bit, 1 char):

    template<typename T>
    string to_byte_string(const T& v)
    {
        char* begin_ = reinterpret_cast<char*>(v);
        return string(begin_, begin_ + sizeof(T));
    }
    
    template<typename T>
    T from_byte_string(std::string& s)
    {
        assert(s.size() == sizeof(T) && "Wrong Type Cast");
        return *(reinterpret_cast<T*>(&s[0]));
    }
    

    This code will also works for structs which are using POD types.

    If you really want the double as two ints

    double d;
    int* data = reinterpret_cast<int*>(&d);
    
    int first = data[0];
    int second = data[1];
    

    Finally, long int will not always be a 64bit integer (I had to use long long int to make a 64bit int on my machine).

    0 讨论(0)
  • 2020-12-18 09:43

    If your doubles are in IEEE 754 format that you should be relatively OK. Now you have to divide their 64 bits into two 32-bit halves and then transmit them in big-endian order (which is network order);

    How about:

    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));
    }
    
    0 讨论(0)
  • 2020-12-18 09:51

    Assuming you have a compile-time option to determine endianness:

    #if BIG_ENDIAN
    template <typename T>
    void swap_endian(T& pX)
    {
       // Don't need to do anything here... 
    }
    #else
    template <typename T>
    void swap_endian(T& pX)
    {
        char& raw = reinterpret_cast<char&>(pX);
        std::reverse(&raw, &raw + sizeof(T));
    }
    #endif
    

    Of course, the other option is to not send double across the network at all - considering that it's not guaranteed to be IEEE-754 compatible - there are machines out there using other floating point formats... Using for example a string would work much better...

    0 讨论(0)
提交回复
热议问题