Bit shift, masking or bit field structure?

I am new to working with bits. I am trying to work with an existing protocol that 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 (the type in my structure above) are always 1 0. The third bit, high, determines whether the signal is on or off, and sig1 + sig2 together determine the 12-bit index of the signal. This index is split into two bytes at 0, which is always at bit 7.

Type 2 is a 32-bit structure. It has a 2-bit type, a 10-bit index, and a 16-bit value, in short with 0 at positions 27, 23, 15, and 7. The structural representation in the bit field should look 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 and sig2 together form a 10-bit index. val1 + val2 + val3 together form a 16-bit signal value at a 10-bit index.

If I understand how to work with the first two structures, I think I can understand the third.

My question is, is there a way to assign one value and the program will produce bits that need to be converted to val1, val2 and val3?

I read about bit offsets, bitfield strings and padding with 0. The structure looks like a way, but I'm not sure how to implement it. None of the bit packing examples that I have seen have values ​​that are separated as they are. Ultimately, I would like to be able to create an analog structure, assign an index (i = 252) and a value (v = 32768) and do with it.

If someone can suggest an appropriate method or provide a link to a similar sample, I would really appreciate it. If that matters, this code will be included in the larger Objective-C application.

Thanks.

Brad

+4
source share
3 answers

You can do this with a series of shifts, and s and or s. I made a 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 10 bits of interest in int i to a range of 16 - 25, then and it with bit mask 0x7f0000 sets bits 22 - 31 to zero. It also transfers another copy of 10 bits to the range 17-26, then and with the bit mask 0x7000000 to set bits 0-22 and 26-31 to zero. Then or two values ​​together, create the desired zero value.

.. I’m not quite sure that I calculated the bitmasks correctly, but I hope you have an idea. Just change, 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 

In the case of the second method of thought, 2 is more readable, so you should probably use this.

+4
source

You cannot use the bit fields of structure C, because the physical location of the bit fields is undefined. Although you could figure out what your compiler does and get the layout to match the underlying data, the code may not work if you switch to another compiler or even upgrade your compiler.

I know this is a pain, but do bit manipulation.

+1
source

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

0
source

Source: https://habr.com/ru/post/955626/


All Articles