c++ - 64 位整数句柄类型的简明位操作

标签 c++ bit-manipulation handle bit-fields

我有一个用作句柄的 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 位类型是更好的选择]

关于c++ - 64 位整数句柄类型的简明位操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24582834/

相关文章:

c++ - 如何等待 Glib::Dispatcher 的连接函数完成?

windows - 为什么使用 GetFileSizeEx() 将文件标记为只读时会出现 "Invalid handle"错误?

Scalatest 中止的测试处理

java - 获取整数中设置位的位置

c++ - Reactor 模式中 File_descriptor 和 Handle 的存储模型

c++ - dll中静态成员变量的生存期

c++ - 如何处理 void decltype();

c++ - 当你从 boost::fibonacci_heap 中删除一个元素时会发生什么?

javascript - javascript中>>>按位移位运算符的用途是什么?

c - 如何使用按位运算返回 0?