1

首先,我想知道这是否可能:假设我有一个 unsigned long ,其中包含一些 abritrary unsigned short ,它可能在数字中,也可能不在数字中。例如:

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

4 回答 4

4

short int是 2 个字节长,但是long long是 8 个字节,所以你有某种长度不匹配;你可能是这个意思:

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

您可以检查是否有一个被ANDing 占用的字段,例如:

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

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

 //etc...
}
于 2010-01-08T00:18:10.520 回答
2

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

因此,首先,您需要使用 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 的“打包”缓冲区,然后将缓冲区与 I/O 一起使用。

于 2010-01-09T00:20:20.883 回答
1

您可能应该查看位移运算符及其工作原理。如果您只是这样做: 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);

   }
于 2010-01-09T02:07:46.047 回答
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
}

这有帮助吗?在处理位时,如果您使用十六进制值,则更容易直观地看到正在发生的事情。

于 2010-01-08T03:14:23.033 回答