Как конвертировать двойной между хостом и сетевым порядком байтов?

Может кто-нибудь сказать мне, как преобразовать двойную точность в сетевой порядок байтов. Я старался

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.

2 ответа

Решение

Вы можете взглянуть на 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.
Btw. Способ возврата значения немного странный.

Но вы могли бы написать более стабильную версию, как это (псевдокод)

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

Это может быть взломано (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;

}

Для краткости я не включил охранников. Тем не менее, вы должны включить охранников диапазона при работе на этом уровне.

Другие вопросы по тегам