Лучший способ отделить длинные / короткие от байтового массива

Поэтому я строю шорты / длинные позиции на основе байтовых массивов, и я хотел бы избежать использования memcpy скопировать байты в их собственную переменную, а затем присвоить эту переменную sockaddr_in объект.

Есть ли лучший способ извлечь short в следующем утверждении?:

((sockaddr_in*)from)->sin_port = (*((unsigned short*)&buf[4]));

Я сделал весь указатель / разыменование, потому что, если моя логика верна, делать только (unsigned short)buf[4] приведение преобразует только один байт; не оба.

РЕДАКТИРОВАТЬ: Endianness в порядке. Я просто хочу, чтобы buf[4] и buf[5] были вместе в одном коротком замысле простым способом, кроме необходимости использовать memcpy,

3 ответа

Решение

Код в вашем вопросе:

(*((unsigned short*)&buf[4]))

может не работать из-за следующих проблем:

memcpy безопасно, если вы уверены в порядке байтов (если нет, то вы должны сочетать с ntohs или же ntohl). Приличный компилятор также должен оптимизировать его.

Если вы действительно хотите избежать memcpy, то безопасный, независимый от платформы способ - это что-то вроде следующего (при условии, что buf изначально был заполнен из внешнего источника, используя стандартный сетевой порядок байтов):

((buf[n] << 8) | buf[n+1])

Конечно, вы должны заключить это в функцию (или макрос, если необходимо).

Я думаю, что правильным решением будет при любых обстоятельствах использовать такие функции, как ntohs а также htons (за long использование ntohl а также htonl).

((sockaddr_in*)from)->sin_port = htons(*((unsigned short*)&buf[4]));

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

Выравнивание может быть другой проблемой на некоторых архитектурах (HP-RISC, SPARC). Функции memcpy а также memmove обычно таких проблем нет. И не стоит оптимизировать преждевременно!

Вы можете использовать макрос ntohs для обработки преобразования порядка байтов, htons означает порядок хост-сеть

((sockaddr_in*)from)->sin_port = htons(*((uint16_t*)&buf[4]));

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

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