LINUX.ORG.RU

Вопрос про endian


0

1

Гуглю на тему независимости от endian. Везде предлагают использовать конверторы по типу htons() etc. Но никак не найду, почему вот такой вариант не будет работать:

//server
void writeInt16(char* buf, int16_t val)
{
  buf[0] = (val >> 8);
  buf[1] = (val & 0xff);
}

//client
int16_t readInt16(const char* buf)
{
  return (buf[0] << 8) + buf[1];
}
Т.е. идея в том, чтобы читать и писать по 8 байт.

★★
Ответ на: комментарий от mv

Весьма сомнительное утверждение. Те же сдвиги и маски. inline разве что в моем варианте не хватает.

kulti ★★
() автор топика
Ответ на: комментарий от kulti

Тогда почему никто так не делает?

А вы посмотрите, как в библиотеках, работающих с форматом bmp, реализуется запись/чтение «шапки».

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от kulti

Некоторые делают. Но зачем, если есть готовые макросы и функции?

unC0Rr ★★★★★
()
Ответ на: комментарий от kulti

> Тогда почему никто так не делает?

4.2. очень многие так делают. разве что эти преобразования критичны во времени, тогда обычно юзают ассемблерные вставки.

arsi ★★★★★
()
Ответ на: комментарий от kulti

Весьма сомнительное утверждение. Те же сдвиги и маски.

У процессоров есть команды для смены endianness. У x86(-64) это xchg для 16-битных значений и bswap для 32- и 64-битных. Реализация ntoh/hton под конкрентную платформу знает, что это за команды и как их использовать.

К тому же, если родной endianness совпадает с network, то hton/ntoh ничего не делает. А ты продолжаешь сериализовать.

mv ★★★★★
()
Ответ на: комментарий от mv

К тому же, если родной endianness совпадает с network, то hton/ntoh ничего не делает. А ты продолжаешь сериализовать.

Стоит заметить, что hton/ntoh работают с выровненными данными. А для чтения невыровненных данных из байтового потока все равно придется сериализовать, даже если endianness совпадает. Поэтому вариант, предложенный ТС, более универсальный.

Deleted
()
Ответ на: комментарий от Deleted

Стоит заметить, что hton/ntoh работают с выровненными данными.

С чего вдруг? Посмотри на их сигнатуры.

А для чтения невыровненных данных из байтового потока все равно придется сериализовать, даже если endianness совпадает.

Не распарсил. Байтовый поток уже сериализован. И при чём здесь поток и выравнивание?

mv ★★★★★
()
Ответ на: комментарий от mv

С чего вдруг? Посмотри на их сигнатуры.

Посмотрел. Принимают/возвращают uint16_t/uint32_t.

И при чём здесь поток и выравнивание?

При том, что вопрос преобразования endianness часто возникает совместно с вопросом чтения бинарных данных из файлов, из сети и т.п. А там данные обычно не выровненные по sizeof uint16_t/uint32_t.

Deleted
()
Ответ на: комментарий от Deleted

При том, что вопрос преобразования endianness часто возникает совместно с вопросом чтения бинарных данных из файлов, из сети и т.п. А там данные обычно не выровненные по sizeof uint16_t/uint32_t.

И? Как связаны процессорный регистр и память, кроме того, что содержимое регистра грузится из памяти?

mv ★★★★★
()
Ответ на: комментарий от mv

Пожалуй, после чтения из памяти в регистр они уже никак не связаны :) Вопрос в скорости или даже в принципиальной возможности выполнения операции чтения из памяти в регистр по адресу, не кратному размеру регистра.

Deleted
()
Ответ на: комментарий от mv

Честно говоря, не очень понимаю, о чем наш спор. Ты же не будешь утверждать, что первый вариант преобразования в этом примере предпочтительней второго:

uint8_t data[3] = { 0xAB, 0xCD, 0xDE };
uint16_t value1 = ntohs (*(uint16_t *)(data + 1));
uint16_t value2 = (data[1] << 8) | data[2];

Разумеется, если исходные данные уже выровнены, то ntohs будет ничем не хуже:

uint8_t data[2] = { 0xCD, 0xDE };
uint16_t value1 = ntohs (*(uint16_t *)data);
uint16_t value2 = (data[0] << 8) | data[1];

Deleted
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.