How to control the degree of duality from the network

I have a BIG problem with the answer to this question Change bit in C ++ to double

However, this question is more or less what I am looking for: I get double from the network, and I want to encode it correctly on my machine.


In the case when I get int , I execute this code with ntohl :

 int * piData = reinterpret_cast<int*>((void*)pData); //manage endianness of incomming network data unsigned long ulValue = ntohl(*piData); int iValue = static_cast<int>(ulValue); 

But in the case when I get double , I do not know what to do.

The answer to the question involves:

 template <typename T> void swap_endian(T& pX) { char& raw = reinterpret_cast<char&>(pX); std::reverse(&raw, &raw + sizeof(T)); } 

However, if I bring this site :

The ntohl() function converts the unsigned integer netlong from network byte order to host byte order. When the two byte orders are different, this means the endian-ness of the data will be changed. When the two byte orders are the same, the data will not be changed.

In contrast, @GManNickG the answer to the question always does the inverse with std::reverse .

Am I really wrong, given that this answer is wrong? (as part of network management endianess, the use of which ntohl suggests, although it was not explicitly indicated in the OP question header).

In the end: should I split my double into two parts of 4 bytes and apply the ntohl function in two parts? Are there any other canonical solutions?

Also this interesting question in C is hosted on a double network? but it is limited to 32-bit values. And the answer says doubles should be converted to strings due to differences in architecture. I am also going to work with sound samples, should I really consider converting all samples to strings in my database? (doubles come from the database I'm querying over the network)

+4
source share
3 answers

If your doubles are in IEEE 754 format, you should be relatively good. Now you need to split your 64 bits into two 32-bit halves, and then transfer them in the big-endian order (which is the network order);

What 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)); } 
+1
source

Assuming you have a compile time option to define an entity:

 #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, another option is that it does not send double over the network at all, assuming that it is not guaranteed to be compatible with IEEE-754 - there are machines there using other floating point formats ... Using, for example, the string will work much it is better...

+1
source

I could not get John Kellen's code to work on my machine. Moreover, it would be more useful to convert double to bytes (8 bits, 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 work for structures that use POD types.

If you really want double to be used 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 64-bit integer (I had to use long long int to make a 64-bit int on my machine).

+1
source

All Articles