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

最佳回答

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...
}
问题回答

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.

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
", a.fields.f1);
      printf("id2 = %d
", a.fields.f2);

   }

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.





相关问题
Undefined reference

I m getting this linker error. I know a way around it, but it s bugging me because another part of the project s linking fine and it s designed almost identically. First, I have namespace LCD. Then I ...

C++ Equivalent of Tidy

Is there an equivalent to tidy for HTML code for C++? I have searched on the internet, but I find nothing but C++ wrappers for tidy, etc... I think the keyword tidy is what has me hung up. I am ...

Template Classes in C++ ... a required skill set?

I m new to C++ and am wondering how much time I should invest in learning how to implement template classes. Are they widely used in industry, or is this something I should move through quickly?

Print possible strings created from a Number

Given a 10 digit Telephone Number, we have to print all possible strings created from that. The mapping of the numbers is the one as exactly on a phone s keypad. i.e. for 1,0-> No Letter for 2->...

typedef ing STL wstring

Why is it when i do the following i get errors when relating to with wchar_t? namespace Foo { typedef std::wstring String; } Now i declare all my strings as Foo::String through out the program, ...

C# Marshal / Pinvoke CBitmap?

I cannot figure out how to marshal a C++ CBitmap to a C# Bitmap or Image class. My import looks like this: [DllImport(@"test.dll", CharSet = CharSet.Unicode)] public static extern IntPtr ...

Window iconification status via Xlib

Is it possible to check with the means of pure X11/Xlib only whether the given window is iconified/minimized, and, if it is, how?

热门标签