解析一个位域参数,如何“丢弃”无符号长整型中的位?

发布于 2024-08-17 07:23:44 字数 788 浏览 9 评论 0原文

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

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)。不知道如何做到这一点,位移位仅向左或向右移动,因此,它仅向右除或乘?


抱歉撞到了。感谢大家的回答,但我最终使用了一种更简单、更有效的方法,即内部结构。您看,我可以使用字符串轻松完成此操作,但我的目的是对代码用户透明,可以说易于编程。 我创建了一个内部结构来保存我的值,然后创建一个公共方法来创建和返回这样的结构,因此它很容易使用并且解析速度更快(尽管它有在堆栈中分配一个(尽管很小)结构的开销,这位域解决方案还没有,但是唉)。

谢谢大家的回答。

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? And is OR the right operation for this? After that let's say I pass bitfld as an argument:

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?


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

So thank you all for your answers.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

余生共白头 2024-08-24 07:23:44

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

short int is 2 bytes long, but long long is 8 bytes, so you have some kind of length mismatch;
You may have meant this:

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

you can check is there is a field occupied by ANDing it like:

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

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

 //etc...
}
时光清浅 2024-08-24 07:23:44

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

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

除非内存空间不足是一个问题,否则这种位打包不值得开发工作、验证时间和额外的执行时间。将这些值放入无符号字符的“打包”缓冲区中,然后将该缓冲区用于 I/O。

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:

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.

转角预定愛 2024-08-24 07:23:44

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

   }

You probably should review the bitshift operators and how they work. If you simply do:
id1 | id2
, you basically mashed all the bits together. You would not be able to extract these values individually later. What you wanted to do is something like id1 | (id2 << 16) as pointed out by the user 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:


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

   }
千笙结 2024-08-24 07:23:44

假设 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
}

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

Assuming unsigned short is 2 bytes and an unsigned long is 4 bytes.

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文