Извлечение битового поля со структурой и порядком байтов в C - PullRequest
0 голосов
/ 16 января 2019

Мне нужно уточнить, как порядок байтов влияет на поле извлечения битов в структуре C.

Следующая структура объявляет заголовок rtp:

typedef struct {
 #if BYTE_ORDER == BIG_ENDIAN
    unsigned int version:2; /* protocol version */
    unsigned int p:1;       /* padding flag */
    unsigned int x:1;       /* header extension flag */
    unsigned int cc:4;      /* CSRC count */
    unsigned int m:1;       /* marker bit */
    unsigned int pt:7;      /* payload type */
#else
   unsigned int cc:4;      /* CSRC count */
   unsigned int x:1;       /* header extension flag */
   unsigned int p:1;       /* padding flag */
   unsigned int version:2; /* protocol version */
   unsigned int pt:7;      /* payload type */
   unsigned int m:1;       /* marker bit */
#endif
  unsigned int seq:16;    /* sequence number */
  uint32_t ts;        /* timestamp */
  uint32_t ssrc;      /* synchronization source */
  uint32_t csrc[0];       /* optional CSRC list */
} rtp_hdr_t;

В связи с тем, что порядок байтов влияет на порядок следования байтов в памяти, я с трудом понимаю, почему структура определяется таким образом в архитектуре с прямым порядком байтов

Спасибо

Ответы [ 2 ]

0 голосов
/ 17 января 2019

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

За 6.7.2 Спецификаторы типа , пункт 11 стандарта C :

Реализация может выделить любую адресуемую единицу хранения, достаточно большую, чтобы содержать битовое поле. Если остается достаточно места, битовое поле, которое следует сразу за другим битовым полем в структуре, должно быть упаковано в смежные биты той же единицы. Если остается недостаточно места, независимо от того, помещается ли битовое поле, которое не помещается, в следующий блок или перекрывает соседние блоки, определяется реализацией. Порядок распределения битовых полей в блоке (от старшего к младшему или от младшего к старшему) определяется реализацией. Выравнивание адресуемой единицы хранения не указано .

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

0 голосов
/ 16 января 2019

Endianness также может влиять на биты, а не только на байты, однако единственный раз, когда вы обычно видите эффекты, находится в битовом поле. Это одна из причин, почему порядок битовых полей в структуре и смещения байтов, в которых они живут, определяется реализацией.

Глядя на это определение, представляется, что для данной реализации битовые поля физически размещаются в порядке в системах с прямым порядком байтов и в обратном порядке для каждого байта в системе с прямым порядком байтов.

В частности, первые 4 битовых поля занимают 8 битов, а следующие 2 битовых поля занимают 8 битов. Таким образом, в случае с прямым порядком байтов порядок первых 4 битовых полей меняются друг на друга, а последние 2 битовых поля меняются друг на друга.

Код подобный этому распространен в системных заголовочных файлах. Например, /usr/include/netinet/in.h в Linux содержит следующую структуру для моделирования заголовка IP:

struct iphdr
  {
#if __BYTE_ORDER == __LITTLE_ENDIAN
    unsigned int ihl:4;
    unsigned int version:4;
#elif __BYTE_ORDER == __BIG_ENDIAN
    unsigned int version:4;
    unsigned int ihl:4;
#else
# error "Please fix <bits/endian.h>"
#endif
    u_int8_t tos;
    u_int16_t tot_len;
    u_int16_t id;
    u_int16_t frag_off;
    u_int8_t ttl;
    u_int8_t protocol;
    u_int16_t check;
    u_int32_t saddr;
    u_int32_t daddr;
    /*The options start here. */
  };

Предположительно, идея состоит в том, что буфер, содержащий необработанный сетевой пакет, может использовать memcpy для копирования байтов в экземпляр этой структуры (или просто иметь указатель на эту структуру, указывающий на буфер, если он выровнен правильно) упростить сериализацию / десериализацию. Вам все равно нужно будет вызвать семейство функций htonx / ntohx, чтобы правильно прочитать целочисленные поля, занимающие более одного байта.

...