Bit Shifting, Masking or a Bit Field Struct?

生来就可爱ヽ(ⅴ<●) 提交于 2019-11-29 22:54:12

问题


I'm new to working with bits. I'm trying to work with an existing protocol, which can send three different types of messages.

Type 1 is a 16-bit structure:

struct digital 
{
 unsigned int type:2;
 unsigned int highlow:1;
 unsigned int sig1:5;
 unsigned int :1;
 unsigned int sig2:7;
};

The first two bits (type, in my struct above) are always 1 0 . The third bit, highlow, determines whether the signal is on or off, and sig1 + sig2 together define the 12-bit index of the signal. This index is split across the two bytes by a 0, which is always in bit 7.

Type 2 is a 32-bit structure. It has a 2-bit type, a 10-bit index and a 16-bit value, interspersed with 0's at positions 27, 23, 15 & 7. A bit-field struct representation would like something like this:

struct analog 
{
 unsigned int type:2;
 unsigned int val1:2;
 unsigned int :1;
 unsigned int sig1:3;
 unsigned int :1;
 unsigned int sig2:7;
 unsigned int :1;
 unsigned int val2:7;
 unsigned int :1;
 unsigned int val3:7;
};

sig1 & sig2 together form the 10-bit index. val1 + val2 + val3 together form the 16-bit value of the signal at the 10-bit index.

If I understand how to work with the first two structs, I think I can figure out the third.

My question is, is there a way to assign a single value and have the program work out the bits that need to go into val1, val2 and val3?

I've read about bit shifting, bit-field structs and padding with 0's. The struct seems like the way to go, but I'm not sure how to implement it. None of the examples of bit-packing that I've seen have values that are split the way these are. Ultimately, I'd like to be able to create an analog struct, assign an index (i = 252) and a value (v = 32768) and be done with it.

If someone could suggest the appropriate method or provide a link to a similar sample, I'd greatly appreciate it. If it matters, this code will be incorporated into a larger Objective-C app.

Thanks.

Brad


回答1:


You can do it with a series of shifts, ands, and ors. I have done the 10-bit index part for Type 2:

unsigned int i = 252;

analog a = (analog)(((i << 16) & 0x7f0000) | (i << 17) & 0x7000000);

Essentially, what this code does is shift the 10 bits of interest in int i to the range 16 - 25, then it ands it with the bitmask 0x7f0000 to set bits 22 - 31 to zero. It also shifts another copy of the 10 bits to the range 17 - 26, then it ands it with the bitmask 0x7000000 to set bits 0 - 22 and 26 - 31 to zero. Then it ors the two values together to create your desired zero-separated value.

.. I'm not absolutely sure that I counted the bitmasks correctly, but I hope you've got the idea. Just shift, and-mask, and or-merge.

Edit: Method 2:

analog a;
a.sig1 = (i & 0x7f); // mask out bit 8 onwards
a.sig2 = ((i<<1) & 0x700); // shift left by one, then mask out bits 0-8

On second thought method 2 is more readable, so you should probably use this.




回答2:


You shouldn't use C structure bitfields because the physical layout of bitfields is undefined. While you could figure out what your compiler is doing and get your layout to match the underlying data, the code may not work if you switch to a different compiler or even update your compiler.

I know it's a pain, but do the bit manipulation yourself.




回答3:


You don't have to do this, this is where the union keyword comes in - you can specify all the bits out at the same time, or by referring to the same bits with a different name, set them all at once.



来源:https://stackoverflow.com/questions/1797345/bit-shifting-masking-or-a-bit-field-struct

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!