4

我需要一个 96 位长的结构,我可以将自定义位字段放入其中。字段的长度无处不在,8, 3, 26, 56。重要的是它们保持这些确切的长度(有一个例外,见下文)。

我看到了许多将数据连接成单个紧凑字段的方法:std::bitset, structs (连续保存字段),当然只使用ints。然而:

  • 这种bitset方法是有问题的,因为操作需要非常快地发生:bitset 没有提供一种方法来立即将 range 设置(x..y)为整个 range (0..96),使用一个原子操作。如果我要循环设置单个位,那该死的。

  • 由于对长度的限制,这种struct方法是有问题的。

  • int方法是有问题的,因为int64_t不够长。我当然可以int32_t在此旁边使用 an ,但是请参见下文。

一个显而易见的解决方案是将56 + 8字段放入int64_t中,将其余部分放入 中int32_t。这里的问题是56-long 字段是唯一一个实际上可能在以后的开发中减少的字段,这意味着我将在.int64_t32 - (26 + 3) = 3int32_t

有什么方法可以尽可能紧凑地存储这些(从代码的角度来看),同时仍然能够通过掩码访问广泛的区域(不像std::bitset)?

4

3 回答 3

3

好的,这里有一个经典的尺寸与速度情况。我要问,在这种情况下,每一点都很重要吗?如果几个比特没有被完全使用,这有什么大不了的吗?我的 C 编码器喜欢 3 个 32 位值的数组,或者 64 位、32 位值的方法。我的优化器不喜欢 96 位数据结构不是完全缓存友好的事实,宁愿填充到 128 位,或者至少不尽可能跨 4 字节边界访问。

根据您的目标平台,使用 64 位值允许在 1 条指令中屏蔽整个 56 位条目,而 32 位版本需要至少 2 次操作。但是,如果您可以将该值降低到 32 位(或最高 64 位),那么,只要您将 64 位值保持在 64 位地址边界上,就完全没有掩码并且全速前进。一些目标将允许您访问未对齐的数据,而其他目标实际上会引发异常。

最安全的方法是 3 个 32 位值的数组。您的对齐得到保证,只要您的位域不跨越 32 位边界,数学就可以保持简单,并且它将是最便携的。如果您必须跨越边界,您将因额外的掩蔽和移位而受到速度打击。但是,这是一个大问题,你真的,真的确定访问这些数据是一个速度问题吗?您手头有一份资料表明这是一个瓶颈?如果没有,我会选择位域 C++ 解决方案并称之为好。更安全、更容易使用几乎总是一种胜利。

于 2011-11-15T16:34:55.580 回答
2
uint32_t bits[3];

在那里,96 位,在一个 POD 类型中,您可以随意使用它。

当然,如果您想要速度,很可能不使用单个位字段会加快速度。但是,如果您确实想在这个级别打包数据,并且std::bitset界面过于受限,那么我会使用一个简单的数组。

于 2011-11-15T14:01:11.020 回答
2

正如我在评论中所说, use bitset,它具有您需要的所有二元运算符,例如:

std::bitset<96> foo(0xFF1); // set bit 1 & bits 5-12

// to test
std::bitset<96> mask(0xFF0); // are bits 5-12 set?
// test, yes the global & operator will create a temporary
if ((mask & foo) == mask)
{
  // do stuff...
}
于 2011-11-15T14:10:33.200 回答