Как управлять бесконечностью двойного из сети

У меня БОЛЬШАЯ проблема с ответом на этот вопрос Поменяйте биты в С ++ для двойного

Тем не менее, этот вопрос более или менее то, что я ищу:
Я получаю дубликат из сети и хочу правильно закодировать его на своем компьютере.

В случае, если я получаю int Я выполняю этот код, используя ntohl :

int * piData = reinterpret_cast<int*>((void*)pData);

//manage endianness of incomming network data
unsigned long ulValue = ntohl(*piData);
int iValue = static_cast<int>(ulValue);

Но в случае я получаю doubleЯ не знаю что делать.

Ответ на вопрос предлагают сделать:

template <typename T>
void swap_endian(T& pX)
{
char& raw = reinterpret_cast<char&>(pX);
std::reverse(&raw, &raw + sizeof(T));
}

Тем не менее, если я цитирую этот сайт:

The ntohl() function converts the unsigned integer netlong from network byte order to host byte order.
When the two byte orders are different, this means the endian-ness of the data will be changed. When the two byte orders are the same, the data will not be changed.

Напротив @ GManNickG ответ на вопрос всегда делает инверсию с std::reverse ,

Я ошибаюсь, считая этот ответ ложным? (в той степени сетевого управления, которые используют ntohl предложить, хотя это не было точно сказано в названии вопроса ОП).

В конце концов: я должен разделить double на две части по 4 байта и применить ntohl функция на две части? Есть ли еще канонические решения?

Там также этот интересный вопрос в C, хост в сеть двойной?, но он ограничивается 32-битными значениями. И ответ говорит, что двойные числа должны быть преобразованы в строки из-за различий в архитектуре … Я также собираюсь поработать с аудио-сэмплами, стоит ли мне действительно подумать о преобразовании всех сэмплов в строки в моей базе данных? (удваивается из базы данных, которую я запрашиваю по сети)

4

Решение

Если ваши двойники в формате IEEE 754, то вы должны быть в порядке. Теперь вы должны разделить их 64 бита на две 32-битные половины, а затем передать их в порядке с прямым порядком байтов (что является сетевым порядком);

Как насчет:

void send_double(double d) {
long int i64 = *((reinterpret_cast<int *>)(&d)); /* Ugly, but works */
int hiword = htonl(static_cast<int>(i64 >> 32));
send(hiword);
int loword = htonl(static_cast<int>(i64));
send(loword);
}

double recv_double() {
int hiword = ntohl(recv_int());
int loword = ntohl(recv_int());
long int i64 = (((static_cast<long int>) hiword) << 32) | loword;
return *((reinterpret_cast<double *>(&i64));
}
2

Другие решения

Предполагая, что у вас есть опция времени компиляции для определения порядка байтов:

#if BIG_ENDIAN
template <typename T>
void swap_endian(T& pX)
{
// Don't need to do anything here...
}
#else
template <typename T>
void swap_endian(T& pX)
{
char& raw = reinterpret_cast<char&>(pX);
std::reverse(&raw, &raw + sizeof(T));
}
#endif

Конечно, другой вариант не отправлять double по всей сети вообще — учитывая, что не гарантируется совместимость с IEEE-754 — есть машины, использующие другие форматы с плавающей запятой … Использование, например, строки будет работать намного лучше …

1

Я не мог заставить код Джона Келлена работать на моей машине. Кроме того, может быть более полезно преобразовать двойное число в байты (8 бит, 1 символ):

template<typename T>
string to_byte_string(const T& v)
{
char* begin_ = reinterpret_cast<char*>(v);
return string(begin_, begin_ + sizeof(T));
}

template<typename T>
T from_byte_string(std::string& s)
{
assert(s.size() == sizeof(T) && "Wrong Type Cast");
return *(reinterpret_cast<T*>(&s[0]));
}

Этот код также работает для структур, которые используют типы POD.

Если вы действительно хотите двойной как две целые

double d;
int* data = reinterpret_cast<int*>(&d);

int first = data[0];
int second = data[1];

В заключение, long int не всегда будет 64-битным целым числом (мне пришлось использовать long long int сделать 64-битный INT на моей машине).

1
По вопросам рекламы [email protected]