Swap bit in C ++ for double

I am trying to move from a large endian to a small terminal double. One way is to use

double val, tmp = 5.55; ((unsigned int *)&val)[0] = ntohl(((unsigned int *)&tmp)[1]); ((unsigned int *)&val)[1] = ntohl(((unsigned int *)&tmp)[0]); 

But then I get a warning: "dereferenced type-guard pointer violates the rules of strict anti-aliasing," and I do not want to turn off this warning.

Another way:

 #define ntohll(x) ( ( (uint64_t)(ntohl( (uint32_t)((x << 32) >> 32) )) << 32) | ntohl( ((uint32_t)(x >> 32)) ) ) val = (double)bswap_64(unsigned long long(tmp)); //or val = (double)ntohll(unsigned long long(tmp)); 

But then lose the decimal places. Does anyone know a good way to swap bits for a double without using a for loop?

+4
source share
3 answers

I would try something like this:

 template <typename T> void swap_endian(T& pX) { // should static assert that T is a POD char& raw = reinterpret_cast<char&>(pX); std::reverse(&raw, &raw + sizeof(T)); } 

Short and sweet (and relatively unverified). The compiler will do all the necessary optimizations. The above is defined for any type of POD and is independent of any implementation details.

Copy version if you do not want to change the argument:

 template <typename T> T swap_endian_copy(T pX) { swap_endian(pX); return pX; } 
+8
source

There are some important issues that need to be addressed when it comes to binary representation of floats or doublings.

+2
source

Can't you just swap them?

 inline unsigned long long EndianChange( double d ) { char ch[8]; memcpy( ch, &d, 8 ); // Note this will be optimised out completely by pretty much every compiler. ch[0] ^= ch[7] ^= ch[0] ^= ch[7]; ch[1] ^= ch[6] ^= ch[1] ^= ch[6]; ch[2] ^= ch[5] ^= ch[2] ^= ch[5]; ch[3] ^= ch[4] ^= ch[3] ^= ch[4]; unsigned long long dRet; memcpy( &dRet, ch, 8 ); // Again this will get optimised out. return dRet; }; 

Edit: as indicated, the bytes are replaced with a double β€œcan” is loaded into the register, so getting it back from this register may mean that the value is no longer valid, so keep it in a long, 64-bit one to avoid this problem.

This is all related to the byte. I'm not sure what you are trying to do, but every large platform I have ever used uses the same encoding as little-endian, only the byte order is reversed. The above code will change the byte order for you. Almost any compiler simply performs byte swapping, and then returns the byte byte variable and gets rid of memcpys. This is a good way to deal with alias problems.

0
source

Source: https://habr.com/ru/post/1307427/


All Articles