Reputation: 8847
Question says it all.
If I have this for a 96-bit field:
uint32_t flags[3]; //(thanks @jalf!)
How do I best go about accessing this, given that my subfields therein may lie over the 32-bit boundaries (eg. a field that runs from bit 29 to 35)?
I need my accesses to be as fast as possible, so I'd rather not iterate over them as 32-bit elements of an array.
Upvotes: 7
Views: 5924
Reputation: 272507
[This answer is valid for C (and by extension, for C++ as well).]
The platform-independent way is to apply bit-masks and bit-shifts as appropriate.
So to get your field from 29 to 35 (inclusive):
(flags[1] & 0xF) << 3
| (flags[0] & 0xE0000000) >> 29 // The bitmask here isn't really needed, but I like symmetry!
Obviously, you could write a class/function/macro to automate this.
Upvotes: 6
Reputation: 37437
There's no problem with bitfields going over 64 bits. They can be even much larger than yours!
The trouble I see, is that you are accessing members that cross a 32 bits boundary. This is more of an issue. But to be honest, on 64 bits platforms, if you use long long
to create your bitfield types, then you only have to be careful on 64 bits boundaries.
If your motivation is to make your accesses "as fast as possible", then think twice before trying to be smarter than the compiler. Nowadays, they can optimize as you're not even aware of. My best recomandation here: keep your code easily readable and understandable.
Upvotes: -1
Reputation: 7043
The STL contains a class for dealing with bitfields of arbitary length:
#include <bitset>
int main() {
const bitset<12> mask(2730ul);
cout << "mask = " << mask << endl;
bitset<12> x;
cout << "Enter a 12-bit bitset in binary: " << flush;
if (cin >> x) {
cout << "x = " << x << endl;
cout << "As ulong: " << x.to_ulong() << endl;
cout << "And with mask: " << (x & mask) << endl;
cout << "Or with mask: " << (x | mask) << endl;
}
}
Upvotes: 11