Разбор параметра поля битов, как «отбросить» биты в беззнаковых длинных? - PullRequest
1 голос
/ 08 января 2010

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

unsigned short int id1 = 3456,
                   id2 = 30998;

unsigned long long bitfld = id1|id2;

Могут ли другие 2 поля быть приняты за 0? И ИЛИ правильная ли операция для этого? После этого, скажем, я передаю bitfld в качестве аргумента:

void dostuff (unsigned long long bf)
{
     //pseudo code
     if( the first field exists in bf)
         get first field;

     if( the second field exists in bf)
         get second field;

     //etc...
}

Я думаю, что мне нужно опросить первые 16 битов битового поля и проверить их, затем рекурсивно опросить их, проверить их и сохранить, если они больше 0. Но я не уверен, как это сделать, бит сдвиг только сдвиг влево или вправо, таким образом, он только делит или умножает вправо?


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

Так что спасибо всем за ваши ответы.

Ответы [ 4 ]

4 голосов
/ 08 января 2010

short int имеет длину 2 байта, но long long имеет длину 8 байтов, поэтому имеется некоторое несоответствие длины; Вы могли иметь в виду это:

unsigned long long bitfld = id1|(id2<<16);

Вы можете проверить, есть ли поле, занятое AND, например:

void dostuff (unsigned long long bf)
{
     //pseudo code
     if(bf & 0xFFFF)
         return bf & 0xFFFF;

     if(bf & 0xFF00)
         return (bf & 0xFFFF0000) >> 32;

 //etc...
}
2 голосов
/ 09 января 2010

Побитовая операция ИЛИ - это не то, что вам нужно. Операция объединит существующих битов с новыми битами. Вы хотите операцию, которая заменяет биты.

Итак, сначала вам нужно очистить биты, используя AND и NOT:

unsigned short int id1 = 3456,
                   id2 = 30998;

unsigned long long bitfld;

unsigned short int all_ones = ~0;
const unsigned int id2_position = 1;
const unsigned int bits_to_shift_left = id2_position * sizeof(unsigned short) * CHAR_BIT;
unsigned long long mask = ~(all_ones << bits_to_shift_left);
bitfld = bitfld & mask; // Erase all bits in id2 position
bitfld = bitfld | (id2 << bits_to_shift_left); // Put value into second position.

Если нехватка места в памяти не является проблемой, этот вид упаковки битов не стоит усилий по разработке, времени проверки и дополнительного времени выполнения. Поместите значения в «упакованный» буфер беззнакового символа, затем используйте буфер с вводом / выводом.

1 голос
/ 09 января 2010

Вы, вероятно, должны рассмотреть операторы битового сдвига и как они работают. Если вы просто делаете: id1 | id2, вы в основном смешиваете все биты вместе. Вы не сможете извлечь эти значения по отдельности позже. То, что вы хотели сделать, это что-то вроде id1 | (id2 << 16), как указано пользователем alemjerus.

Еще один способ достижения той же цели без ударов битами - использовать объединение:


   struct s_btfld {
       unsigned short int f1;
       unsigned short int f2;
       unsigned short int f3;
       unsigned short int f4;
   };

   union u_btfld {
       struct s_btfld     fields;
       unsigned long long value;
   };

Теперь вы можете сделать:


   unsigned short int id1 = 3456, id2 = 30998;

   union u_btfld bitfld;

   bitfld.fields.f1 = id1;
   bitfld.fields.f2 = id2;

   dostuff(bitfld.value);

А в dostuff вы можете легко получить поля:


   void dostuff(unsigned long long bf) {

      union u_btfld a;

      a.value = bf;

      printf("id1 = %d\n", a.fields.f1);
      printf("id2 = %d\n", a.fields.f2);

   }
0 голосов
/ 08 января 2010

Предполагается, что длина без знака - 2 байта, а длина без знака - 4 байта.

unsigned short id1 = 0x0d80; //3456 decimal
unsigned short id2 = 0x7916; //30998 decimal
unsigned long bitfld = ((id2<<16)|id1)  //id2<<16 = 0x79160000, so bitfld = 0x79160d80
if ((bitfld & id1) == id1) {
    //id1 is in lower 2 bytes of bitfld
}
if ((bitfld>>16) &id2) == id2) { //bitfld>>16 = 0x00007916
    //id2 is in upper 2 bytes of bitfld
}

Это помогает? При работе с битами легче визуально увидеть, что происходит, если вы работаете с шестнадцатеричными значениями.

...