Как упаковать данные в двоичном формате в C ++ - PullRequest
3 голосов
/ 17 января 2012

Скажем, у меня есть двоичный протокол, где первые 4 бита представляют собой числовое значение, которое может быть меньше или равно 10 (десять в десятичном виде).

В C ++ наименьший доступный мне тип данных - это char, длина которого составляет 8 бит.Таким образом, в моем приложении я могу хранить значение, представленное 4 битами, в переменной типа char.Мой вопрос: если мне нужно упаковать значение символа обратно в 4 бита для передачи по сети, как мне упаковать значение моего символа обратно в 4 бита?

Ответы [ 4 ]

4 голосов
/ 17 января 2012

Вы выполняете битовую операцию над символом;

, поэтому

  unsigned char packedvalue = 0;

  packedvalue |= 0xF0 & (7 <<4);
  packedvalue |= 0x0F & (10);

Установите 4 старших старших бита на 7, а младших 4 бита на 10

Распаковывая этиснова как

 int upper, lower;

 upper = (packedvalue & 0xF0) >>4;
 lower = packedvalue & 0x0F;

В качестве дополнительного ответа на вопрос - вы также можете посмотреть буферы протокола для способа кодирования и декодирования данных для двоичных передач.

3 голосов
/ 17 января 2012

Ну, есть популярные, но непереносимые «битовые поля». Они соответствуют стандарту, но могут создавать разные заказы на упаковку на разных платформах. Так что не используйте их.

Далее, есть очень переносимые операторы битового сдвига и побитового И и ИЛИ, которые вы должны предпочесть. По сути, вы работаете с большим полем (обычно 32 бита, для протоколов TCP / IP) и извлекаете или заменяете подпоследовательности битов. См. Ссылку Мартина и ответ Сорена на них.

3 голосов
/ 17 января 2012

Конечно, просто используйте один символ в качестве значения:

std::ofstream outfile("thefile.bin", std::ios::binary);

unsigned int n;  // at most 10!
char c = n << 4; // fits
outfile.write(&c, 1);  // we wrote the value "10"

Младшие 4 бита останутся равными нулю. Если они также используются для чего-то, вам придется полностью заполнить c, прежде чем писать. Читать:

infile.read(&c, 1);
unsigned int n = c >> 4;
0 голосов
/ 17 января 2012

Вы знакомы с битовыми полями C ? Вы просто пишете

struct my_bits {
  unsigned v1 : 4;
  ...
};

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

Вы также должны позаботиться о порядке байтов и потоков (подробности см. В статье Википедии, на которую я ссылался, но проблемы вроде бы очевидны). В любом случае, вы должны учиться о порядке байтов, поскольку вы сказали «двоичный протокол» (см. в предыдущих вопросах )

...