如何在主机和网络字节顺序之间转换双倍?

时间:2012-05-16 10:42:32

标签: networking linux-kernel embedded arm endianness

有人可以告诉我如何将双精度转换为网络字节排序。 我试过了

uint32_t htonl(uint32_t hostlong);
uint16_t htons(uint16_t hostshort);
uint32_t ntohl(uint32_t netlong);
uint16_t ntohs(uint16_t netshort);

函数并且它们运行良好但它们都没有进行双(浮点)转换,因为这些类型在每个体系结构上都不同。通过XDR,我发现了双浮点精度格式表示(http://en.wikipedia.org/wiki/Double_precision)但没有字节排序。

所以,如果有人帮我解决这个问题,我会非常感激(C代码会很棒!)。 注意:操作系统是Linux内核(2.6.29),ARMv7 CPU架构。

2 个答案:

答案 0 :(得分:4)

您可以在浮点的交换格式中查看IEEE 754

但关键应该是定义一个网络订单,例如。 1.字节指数和符号,字节2到n作为尾数,以msb为单位。

然后你可以声明你的功能

uint64_t htond(double hostdouble);
double ntohd(uint64_t netdouble);

实现仅取决于您的编译器/平台 最好的方法是使用一些自然定义, 所以你可以在ARM平台上使用简单的转换。

编辑:

来自评论

static void htond (double &x)
{
  int *Double_Overlay; 
  int Holding_Buffer; 
  Double_Overlay = (int *) &x; 
  Holding_Buffer = Double_Overlay [0]; 
  Double_Overlay [0] = htonl (Double_Overlay [1]); 
  Double_Overlay [1] = htonl (Holding_Buffer); 
}

这可能有效,但显然只有当两个平台对double使用相同的编码模式并且int具有相同的long长度时。 顺便说一句。返回值的方式有点奇怪。

但是你可以写一个更稳定的版本,比如这个(伪代码)

void htond (const double hostDouble, uint8_t result[8])
{
  result[0] = signOf(hostDouble);
  result[1] = exponentOf(hostDouble);
  result[2..7] = mantissaOf(hostDouble);
}

答案 1 :(得分:1)

这可能是hacky(char * hack),但它对我有用:

double Buffer::get8AsDouble(){

    double little_endian = *(double*)this->cursor;

    double big_endian;

    int x = 0;
    char *little_pointer = (char*)&little_endian;
    char *big_pointer = (char*)&big_endian;

    while( x < 8 ){
        big_pointer[x] = little_pointer[7 - x];
        ++x;
    }

    return big_endian;

}

为简洁起见,我没有包括护卫队。但是,在这个级别工作时,你应该包括护卫员。