Как конвертировать двойной между хостом и сетевым порядком байтов?
Может кто-нибудь сказать мне, как преобразовать двойную точность в сетевой порядок байтов. Я старался
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;
}
Для краткости я не включил охранников. Тем не менее, вы должны включить охранников диапазона при работе на этом уровне.