Little endian to Big endian conversion в C++, необходим ли для бинарной сериализации?

Собственно, есть кроссплатформенный код. Задача стоит реализовать бинарное сохранение данных, данные потом будут читаться не только с с++.
Я так понял, в Windows Little Endian. Но есть платформы, где у нас Big Endian.

Что я хочу - написать такой код, который гарантировано будет сохранять в сетевом порядке байты (Big Endian).
Что я пока придумал:

Некий макрос, например, отсюда: stackoverflow.com/questions/2100331/c-macro-defini...

тогда функция будет иметь такой вид:

void saveInt(int a)
{
#ifdef BIG_ENDIAN
save(a);
#else // little endian
int b = htonl(a);
save(b);
#endif
}


Может, можно как-то веселее такое реализовать, а то такую функцию для каждого типа данных писать.
Ну и верно ли я понял, что htons всегда переворачивает байты? Если нет, то получается, такой код не нужен, просто всегда вызывать ее, а у нее внутри что-то вроде кода, который я написал.
  • Вопрос задан
  • 4859 просмотров
Решения вопроса 2
@xandox
В posix системах (в винде проверить не могу, но скорее всего то же где-то должно быть) есть семейство функций для работы с big endian и little endian.

По поводу твоего вопроса я бы сделал примерно так
unsigned short store(unsigned short s) { return htobe16(s); }
unsigned int store(unsigned int s) { return htobe32(s); }
unsinged long store(unsigned long s) { if (sizeof(unsinged long) == 8) return htobe64(s); else return htobe32(s);}

unsigned short restore(unsinged short s) { return be16toh(s); }
// и т.д.


ну тут как видишь тебе придется еще решить вопрос с unsinged long. он, в зависимости, от битности системы имеет разный размер.

PS. На самом деле big endian встречается сейчас только на встраиваемых системах и на игровых консолях и вообще говоря зависит не от ОС, а от процессора. На x86 и amd64 всегда little endian. По сему подумай - а надо ли тебе это.
Ответ написан
Функция htonl конвертирует host порядок байт в сетевой порядок байт (т. е. в Big Endian), независимо от того, какой на самом деле на host используется порядок, т. е. вся препроцессорная логика не нужна (она уже есть в htonl).

Порядок байт нужно зафиксировать, но он не обязан быть Big Endian, можно с успехом использовать Little Endian, и если все платформы работают с последним, то париться не придется вообще, если же есть Big Endian клиент, то парится придется только на нем (если конечно не хочется написать один код для всех клиентов, в этом случае лучше использовать htons или аналогичную функцию для Little Endian).

Если говорить о бинарной сериализации, то фиксировать нужно не только порядок байт, но и размер, т. е. использовать типы вроде uint32_t. Функции hton* и так их используют, но у тебя в коде используется int, что не очень хорошо.
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы