64位整型句柄类型的简洁位操作
Concise bit-manipulation for 64bit integer handle type
我有一个64位整数用作句柄。64位必须分割成以下字段,以便单独访问:
size : 30 bits
offset : 30 bits
invalid flag : 1 bit
immutable flag : 1 bit
type flag : 1 bit
mapped flag : 1 bit
我能想到的两种方法是:
1)传统的位操作(& | << >>
)等。但我觉得这有点神秘。
2)使用位域结构体:
#pragma pack(push, 1)
struct Handle {
uint32_t size : 30;
uint32_t offset : 30;
uint8_t invalid : 1;
uint8_t immutable : 1;
uint8_t type : 1;
uint8_t mapped : 1;
};
#pragma pack(pop)
那么访问一个字段就变得非常清楚了:
handle.invalid = 1;
但是我知道位域很有问题,而且不可移植。
我正在寻找实现这个位操作的方法,以最大限度地提高代码的清晰度和可读性。我应该采取哪种方法?
指出:
句柄大小不能超过64位;
只要尊重每个字段的大小,这些字段在内存中放置的顺序是无关的;
句柄没有保存/加载到文件中,所以我不必担心尾序
我会选择位域解决方案。
位域只有在您希望以二进制形式存储,然后使用不同的编译器或更常见的是,在不同的机器架构上读取该位域时才"不可移植"。这主要是因为标准没有定义字段顺序。
在您的应用程序中使用位域是可以的,只要您不需要"二进制可移植性"(将您的Handle
存储在一个文件中,并在不同的系统上使用由不同的编译器或不同的处理器类型编译的代码来读取它),它就会工作得很好。
显然,你需要做一些检查,例如sizeof(Handle) == 8
应该在某个地方完成,以确保你得到正确的大小,编译器还没有决定把你的两个30位值放在单独的32位字中。为了提高在多个体系结构上成功的机会,我可能会将类型定义为:
struct Handle {
uint64_t size : 30;
uint64_t offset : 30;
uint64_t invalid : 1;
uint64_t immutable : 1;
uint64_t type : 1;
uint64_t mapped : 1;
};
有一些规则,编译器不应该"拆分元素",如果你定义的东西为uint32_t,只有两个比特留在字段,整个30位移动到下一个32位元素。[它可能在大多数编译器中工作,但以防万一,使用相同的64位类型是一个更好的选择]
我推荐位操作。当然,您应该将所有这些操作隐藏在类中。提供成员函数来执行set/get操作。在类中明智地使用常量将使大多数操作相当透明。例如:
bool Handle::isMutable() const {
return bits & MUTABLE;
}
void Handle::setMutable(bool f) {
if (f)
bits |= MUTABLE;
else
bits &= ~MUTABLE;
}
- 对字符串进行位操作
- 对字符数组中的元素执行逐位操作
- 逐位操作的隐式类型转换
- 如何进行特定的位操作?
- C++避免位操作完全移位
- 使用双包装器类进行位操作(C++、clang)修复性能下降问题
- 使用位操作优化检查
- 子集相关位操作
- 使用 c++ 提升库的按位操作
- 位操作和异或
- 位操作将最左侧的设置位转换为右侧交替位?
- 为什么对小于 4 个字节的整数类型的位操作会发生意外行为?
- POD 类型的原子按位操作
- 如何使用位操作在单个整数中编码和解码两个数字
- __int128的位操作
- 使用位操作会影响内存消耗?
- 在具有位操作的函数中获得值
- C/C 位操作不会导致预期输出
- 在数组大小中使用位操作的原因
- 64位整型句柄类型的简洁位操作