问题已经说得很清楚了。
如果我有一个96位的字段:
如果我有一个96位的字段:
uint32_t flags[3]; //(thanks @jalf!)
如果我的子字段可能跨越32位边界(例如,从第29位到第35位运行的字段),那么我应该如何最好地访问它?
我需要尽可能快地访问它们,因此我不想按32位数组元素进行迭代。
uint32_t flags[3]; //(thanks @jalf!)
如果我的子字段可能跨越32位边界(例如,从第29位到第35位运行的字段),那么我应该如何最好地访问它?
我需要尽可能快地访问它们,因此我不想按32位数组元素进行迭代。
STL 包含一个用于处理任意长度的位域(bitfields)的类:
#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;
}
}
std::bitset
比替代方案慢吗?请考虑这段代码,它编译成了这段汇编代码。std::bitset
的解决方案有三个内存加载、两个移位、一个“或”和一个“与”。手写的解决方案有三个加载、两个移位、一个“或”和两个“与”。 - Robᵩ[此答案适用于C语言(并且也适用于C++)。]
跨平台的方法是根据需要应用位掩码和位移。
因此,要从29到35(包括这两个数)获取您的字段:
(flags[1] & 0xF) << 3
| (flags[0] & 0xE0000000) >> 29 // The bitmask here isn't really needed, but I like symmetry!
位域超过64位并没有问题。它们甚至可以比你的更大!
我看到的问题是,你正在访问跨越32位边界的成员。这是一个更大的问题。但说实话,在64位平台上,如果你使用long long
来创建你的位域类型,那么你只需要在64位边界上小心谨慎。
如果你的动机是为了使你的访问“尽可能快”,那么在试图比编译器更聪明之前三思而后行。现在,他们可以进行优化,而你甚至没有意识到。我最好的建议是:保持你的代码易于阅读和理解。
__uint128_t
。 - Jens Gustedt