【问题标题】:Swap bits in c++ for a double将 C++ 中的位交换为双精度
【发布时间】:2010-04-20 07:42:34
【问题描述】:

我正在尝试将双精度从大端更改为小端。一种方法是使用

double val, tmp = 5.55;

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

然后我收到一条警告:“取消引用类型双关指针会破坏严格的别名规则”,我不想关闭此警告。

另一种方法是:

#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));

但随后会丢失小数点。 任何人都知道在不使用 for 循环的情况下交换双精度位的好方法吗?

【问题讨论】:

  • 如果您在 C++ 中执行此操作,我相信您应该避免使用 C 风格的强制转换。
  • 我昨天遇到了类似的问题,你可能对答案感兴趣(stackoverflow.com/questions/2667225/…
  • 我检查了你的问题的答案,我的解决方案没问题,谢谢

标签: c++ floating-point double bits endianness


【解决方案1】:

我可能会尝试这样的事情:

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));
}

短而甜(相对未经测试)。编译器将进行所有必要的优化。以上对任何 POD 类型都进行了很好的定义,并且不依赖于任何实现细节。

复制版本,当您不想修改参数时:

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

【讨论】:

    【解决方案2】:

    在处理浮点数或双精度数的二进制表示时有some important pitfalls to pay attention to

    【讨论】:

      【解决方案3】:

      你不能把它们换掉吗?

      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;
      };
      

      编辑:正如所指出的,字节交换双“可以”被加载到寄存器中,以便将其从该寄存器中取回可能意味着该值不再有效,因此将其存储在 long long、64 位以避免这个问题。

      这就是字节交换的全部内容。我不确定您要做什么,但是我曾经使用过的每个大端平台都使用与小端相同的编码,只是颠倒了字节顺序。上面的代码将为您反转字节顺序。几乎任何编译器都会简单地进行字节交换,然后返回字节交换变量并摆脱 memcpys。这是处理别名问题的好方法。

      【讨论】:

      • 这个解决方案绝对行不通——一个字节序改变的双精度可能不再是一个有效的 FP 值,并且会导致 FPU 中的未定义行为。请参阅@Max Lybbert 的链接。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-04-24
      • 1970-01-01
      • 2014-01-01
      • 2015-09-13
      • 2010-10-19
      • 2013-10-10
      • 2015-04-10
      相关资源
      最近更新 更多