简体   繁体   English

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

[英]Parsing a bit field parameter, how to “discard” bits in an unsigned long?

First of all, I want to know if this is possible: let's say I have an unsigned long which contains some abritrary unsigned shorts, which may or may not be in the number. 首先,我想知道这是否有可能:假设我有一个无符号的长单,其中包含一些无符号的短裤,可能不在数字中。 For example: 例如:

unsigned short int id1 = 3456,
                   id2 = 30998;

unsigned long long bitfld = id1|id2;

Can the other 2 fields be assumed as 0? 能否将其他2个字段假定为0? And is OR the right operation for this? 或者对此是否进行正确的操作? After that let's say I pass bitfld as an argument: 之后,假设我将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...
}

I think I have to poll out the first 16 bits of the bitfield and check those, then recursively poll them, verify them and store them if they are greater than 0. But I'm not sure how to do this, bit shifting only shifts left or right, thus, it only divides or multiplies right? 我想我必须轮询出位域的前16位,然后检查它们,然后递归地对其进行轮询,验证它们并存储,如果它们大于0。但是我不确定如何执行此操作,移位仅移位左或右,因此,它只除或乘右?


sorry for the bump. 抱歉! Thanks all for your answers, but I ended up using a simpler and more efficient method, an internal structure. 感谢大家的回答,但最后我使用了一种更简单,更有效的方法,即内部结构。 You see, I could have done this easily with a string, but my purpose was transparency to the user of the code, easy to program so to say. 您看,我可以使用字符串轻松完成此操作,但是我的目的是使代码用户透明,可以这么容易地编程。 I created an internal structure to hold my values and then a public method to create and return such structure, so it is easy to use and faster to parse (though it has the overhead of allocating in the stack a (albeit small) structure, which the bit field solution hasn't, but alas). 我创建了一个内部结构来保存我的值,然后创建一个公共方法来创建和返回这种结构,因此它易于使用且解析速度更快(尽管它在堆栈中分配(尽管很小)结构的开销很大),位域解决方案还没有,但是a)。

So thank you all for your answers. 因此,谢谢大家的回答。

short int is 2 bytes long, but long long is 8 bytes, so you have some kind of length mismatch; short int是2个字节长,而long long是8个字节,因此您存在某种长度不匹配的情况; You may have meant this: 您可能是这个意思:

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

you can check is there is a field occupied by AND ing it like: 您可以检查是否有AND占用的字段,例如:

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

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

 //etc...
}

The bitwise OR operation is not what you want. 按位或运算不是您想要的。 The operation will merge existing bits with the new bits. 该操作将现有位与新位合并 You want an operation that replaces bits. 您需要一个替换位的操作。

So first, you will need to clear out the bits using AND and NOT: 因此,首先,您需要使用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.

Unless lack of memory space is an issue, this kind of bit packing is not worth the development effort, validation time and extra execution time. 除非缺少内存空间是一个问题,否则这种位打包不值得进行开发工作,验证时间和额外的执行时间。 Place the values into a "packed" buffer of unsigned char, then use the buffer with I/O. 将值放入无符号字符的“打包”缓冲区中,然后将该缓冲区与I / O一起使用。

You probably should review the bitshift operators and how they work. 您可能应该查看位移位运算符及其工作方式。 If you simply do: id1 | id2 如果您只是这样做: id1 | id2 id1 | id2 , you basically mashed all the bits together. id1 | id2 ,您基本上将所有位id1 | id2在一起。 You would not be able to extract these values individually later. 您将无法在以后单独提取这些值。 What you wanted to do is something like id1 | (id2 << 16) 您想要做的是像id1 | (id2 << 16) id1 | (id2 << 16) as pointed out by the user alemjerus. id1 | (id2 << 16) ,由用户alemjerus指出。

Another way of accomplishing the same goal without bitshitting is to use a union: 另一些无需花钱就能达到相同目标的方法是使用联合:


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

Now you can do: 现在您可以执行以下操作:


   unsigned short int id1 = 3456, id2 = 30998;

   union u_btfld bitfld;

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

   dostuff(bitfld.value);

And in dostuff, you can easily retrieve the fields by: 在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);

   }

Assuming unsigned short is 2 bytes and an unsigned long is 4 bytes. 假设无符号短为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
}

Does this help? 这有帮助吗? When dealing with bits it's easier to visually see what is happening if you work with hex values. 处理位时,如果使用十六进制值,则更容易直观地看到发生了什么。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM