具有非八位位组对齐子场的96位长位域

时间:2011-11-15 13:45:47

标签: c++ gcc bit-manipulation bit-fields bitset

我需要一个96位长的结构,我可以将自定义位字段放入其中。字段的长度遍布各处,832656。重要的是它们保持这些精确的长度(有一个例外,见下文)。

我看到了将数据连接到单个紧凑字段的多种方法:std::bitsetstruct s(连续保持字段),当然只使用int s。但是:

  • bitset方法存在问题,因为操作需要非常快速地执行:bitset不提供立即在整个范围(x..y)范围内设置范围(0..96)的方法,用一个原子操作。如果我要循环设置个别位,该死的。

  • 由于this长度限制,struct方法存在问题。

  • int方法存在问题,因为int64_t不够长。我当然可以使用int32_t,但请参见下文。

显而易见的一个解决方案是将56 + 8字段放入int64_t,其余字段放入int32_t。这里的问题是56 - 长字段是唯一一个事实上可能在后期开发中减少的字段,这意味着我将在int64_t中有一些备用位,有些{ {1}}中的{1}}备用位。

是否有任何方法可以尽可能紧凑地存储这些内容(从代码的角度来看),同时仍然可以通过屏蔽访问广泛的区域(与32 - (26 + 3) = 3不同)?

3 个答案:

答案 0 :(得分:3)

好的,你有一个经典的尺寸与速度的情况。我要问,这是一种每一点都重要的情况吗?如果没有使用几个位,这是一件大事吗?我的C编码器喜欢3个32位值的数组,或者64位32位值的方法。我的优化器不喜欢这样的事实:96位数据结构不是完全缓存友好的,而是填充到128位,或者至少不能跨越4字节边界访问。

使用64位值(取决于您的目标平台)允许在1条指令中屏蔽整个56位条目,而32位版本至少需要2条操作。但是,如果你可以将该值降低到32位(或高达64位),那么,如果在64位地址边界上保留64位值,则根本不需要屏蔽和全速。一些目标将允许您以惩罚方式访问数据,而其他目标实际上会抛出异常。

最安全的方法是3个32位值的数组。您的对齐是有保证的,只要您没有与位域跨越32位边界,数学就可以保持简单,并且它将是最便携的。如果你必须跨越边界,你将通过额外的掩蔽和移动来获得速度。但是,这是一个大问题,你真的,真的确定访问这些数据是速度问题吗?您手头有个人资料显示这是一个瓶颈吗?如果没有,我只需要使用bitfield C ++解决方案并将其称为好。更安全,更容易使用几乎总是一个胜利。

答案 1 :(得分:2)

uint32_t bits[3];

有一个POD类型的96位,您可以根据自己的喜好进行搜索。

当然,如果你想要速度,很可能不使用单个位字段会加快速度。但是如果你想要在这个级别打包你的数据,并且std::bitset接口太过限制,我就会使用一个简单的数组。

答案 2 :(得分:2)

正如我在评论中所说,使用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...
}