解析一个位字段参数,如何“丢弃”无符号长整数位?

时间:2010-01-08 00:11:29

标签: c++ c bit-manipulation parameter-passing bit-fields

首先,我想知道这是否可行:假设我有一个无符号长整数,其中包含一些无用的无符号短路,这些短路可能在数字中,也可能不在数字中。例如:

unsigned short int id1 = 3456,
                   id2 = 30998;

unsigned long long bitfld = id1|id2;

其他2个字段可以假定为0吗? OR是正确的操作吗?在那之后让我们说我将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 个答案:

答案 0 :(得分:4)

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...
}

答案 1 :(得分:2)

按位OR运算不是您想要的。该操作将合并现有位与新位。您需要一个替换位的操作。

首先,您需要使用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.

除非缺少内存空间是一个问题,否则这种打包工作不值得开发,验证时间和额外的执行时间。将值放入unsigned char的“packed”缓冲区中,然后将缓冲区与I / O一起使用。

答案 2 :(得分:1)

您可能应该查看bitshift运算符及其工作原理。如果您只是执行: id1 | id2,您基本上将所有位混合在一起。您将无法在以后单独提取这些值。您想要做的是像用户alemjerus所指出的那样id1 | (id2 << 16)

实现相同目标的另一种方法是使用联合:


   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);

   }

答案 3 :(得分:0)

假设unsigned short是2个字节而unsigned long是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
}

这有帮助吗? 处理位时,如果使用十六进制值,则可以更直观地查看发生的情况。