English 中文(简体)
Bit Shifting, Masking or a Bit Field Struct?
原标题:

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

问题回答

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.

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.

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.





相关问题
Fastest method for running a binary search on a file in C?

For example, let s say I want to find a particular word or number in a file. The contents are in sorted order (obviously). Since I want to run a binary search on the file, it seems like a real waste ...

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

Tips for debugging a made-for-linux application on windows?

I m trying to find the source of a bug I have found in an open-source application. I have managed to get a build up and running on my Windows machine, but I m having trouble finding the spot in the ...

Trying to split by two delimiters and it doesn t work - C

I wrote below code to readin line by line from stdin ex. city=Boston;city=New York;city=Chicago and then split each line by ; delimiter and print each record. Then in yet another loop I try to ...

Good, free, easy-to-use C graphics libraries? [closed]

I was wondering if there were any good free graphics libraries for C that are easy to use? It s for plotting 2d and 3d graphs and then saving to a file. It s on a Linux system and there s no gnuplot ...

Encoding, decoding an integer to a char array

Please note that this is not homework and i did search before starting this new thread. I got Store an int in a char array? I was looking for an answer but didn t get any satisfactory answer in the ...

热门标签