Самый простой способ - вручную перестроить uint16_t
s за счет скорости:
uint8_t *packet = ...;
uint16_t fieldID = (packet[0] << 8) | packet[1]; // assumes big-endian host order
uint16_t length = (packet[2] << 8) | packet[2];
uint8_t *data = packet + 4;
packet += 4 + length;
Если ваш процессор поддерживает его, вы можете набрать каламбур или использовать объединение (но остерегайтесь строгого алиасинга ).
uint16_t fieldID = htons(*(uint16_t *)packet);
uint16_t length = htons(*(uint16_t *)(packet + 2));
Обратите внимание, что не выровненный доступ не всегда поддерживается (например, они могут генерировать какой-либо сбой), а на других архитектурах они поддерживаются, но существует снижение производительности.
Если пакет не выровнен, вы всегда можете скопировать его в статический буфер и затем прочитать его:
static char static_buffer[65540];
memcpy(static_buffer, packet, packet_size); // make sure packet_size <= 65540
uint16_t fieldId = htons(*(uint16_t *)static_buffer);
uint16_t length = htons(*(uint16_t *)(static_buffer + 2));
Лично я бы просто выбрал вариант № 1, поскольку он будет наиболее переносимым.