Примитивные типы данных C ++: как читать беззнаковые 30 бит - PullRequest
1 голос
/ 12 июля 2010

У меня есть массив unsigned chars.В основном у меня есть массив битов.

Я знаю, что первые 16 битов соответствуют целому числу без знака, и я извлекаю его значение, используя (u16)(*(buffer+ 1) << 8 | *abcBuffer)

Затем следует тип данных с именем u30, который описывается следующим образом: u30 - variable length encoded 30-bit unsigned integer value.Переменная кодировка для u30 использует от одного до пяти байтов, в зависимости от величины закодированного значения.Каждый байт вносит свои семь младших битов в значение. Если старший (8-й) бит байта установлен, то следующий байт также является частью значения.

Я не понимаю этого описания: там написано u30 (тридцать!), А потом написано от 1 до 5 байтов?Также у меня есть другой тип данных, который называется s24 - three-byte signed integer value.

Как следует читать (извлекать их значения) такие нетипичные типы данных?Любая помощь будет оценена.

Большое спасибо!

Ответы [ 4 ]

4 голосов
/ 12 июля 2010
i=0;    
val = buf[i]&0x7F;
while (buf[i++]&0x80)
{ 
  val |= (buf[i]&0x7F)<<(i*7);
}
2 голосов
/ 12 июля 2010

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

   unsigned int val;
   unsigned char buf[300];
   int i;
   int shift;

   i = 0;

   buf[0] = 0x81;
   buf[1] = 0x3;
   val = 0;
   shift = 0;
   do
      {
      val |= (0x7F & buf[i] ) << shift;
      shift += 7;
      i++;
      } while (( buf[i-1] & 0x80 ) && ( i < 5 ));
   printf( "Val = %u\n", val );
1 голос
/ 12 июля 2010

Описание формата кодирования, возможно, несколько неформально, но этого должно быть достаточно. Идея будет заключаться в том, что вы читаете один байт (назовите его x), берете младшие 7 бит x & 0x7F и в то же время проверяете, установлен ли его старший бит. Вам нужно написать небольшой цикл, который объединяет 7-битные последовательности в переменную uint до тех пор, пока текущий байт больше не установит свой старший бит.

Вам нужно будет выяснить, нужно ли объединять новые биты в верхнем или нижнем конце числа (a = (a << 7) | (x & 0x7F)). Для этого вам нужна одна тестовая последовательность, из которой вы знаете, каков правильный вывод.

0 голосов
/ 12 июля 2010

Чтобы прочитать 30-битное значение переменной длины, вы можете сделать что-то вроде этого:

const char HIGH_BIT = 0x80;
const char DATA_MASK = 0x7F;
const char LAST_MASK = 0x03; // only need 2 bits of last byte
char tmpValue = 0; // tmp holder for value of byte;
int value = 0; holder for the actual value;
char* ptr = buffer; // assume buffer is at the start of the 30 bit number
for(int i = 0; i < 5; i++)
{
   if(i == 4)
   {
      tmpValue = LAST_MASK & *ptr;
   }
   else
   {
      tmpValue = DATA_MASK & *ptr;
   }

   value |= tmpValue << ( 7 * i);

   if(!(HIGH_BIT & *ptr))
   {
      break;
   }
   if(i != 4)
   {
     ++ptr;
   }
}
buff = ptr; // advance the buffer afterwards.

@ Марк: ваш ответ был опубликован, пока я набирал это, и работал бы, за исключением старшего байта. значение составляет только 30 битов, поэтому для значения используются только первые 2 бита старшего байта, и вы используете полные 8 битов значения.

...