在异常大小的单词上使用掩码

Using masks on abnormally sized words

我正在编写一些需要 code/decode 56 位(7 字节)字和 112 位(14 字节)字的代码。

我习惯于处理32位的字。如果我需要从一个词中提取第 23-25 位,我只需要这样做:

int unpackBits23To25( uint32_t word )
{
    return (word>>22) & 0x7;
}

或者像这样更通用的方式:

int unpackBits( uint8_t word[14], int startbit, int endbit )
{
  int mask = (0x1 << (endbit - startbit + 1)) - 1;
  return (word >> (startbit - 1)) & mask;
}

很容易看出我正在尝试做什么(转换和遮罩)。但是,如果我从 112 位字中提取第 23-25 位呢?而不是使用 uint32_t 我需要使用其他东西。 uint64_t 适用于 56 位字,但由于我也有 112 位字,因此我需要将它存储在一个数组中。 uint8_t[14] 可能是我最好的选择。

int unpackBits23To25( uint8_t word[14] )
{
  return ((word[5] >> 3) & 0x1) | ((word[6] << 1) & 0x6);
}

并不难写,但如果你想read/troubleshoot它是完全难以辨认的。我还没有尝试过通用解决方案,但我有一种感觉,它会成为一个怪物。

您建议如何对晦涩的字长进行按位运算?

这是从被视为位数组的字节数组中提取单个位的通用方法:

uint8_t value = (word[bit/8] & (1 << (bit%8)) != 0;

对于给定范围的要提取的位,您可以遍历每个位并将它们放入结果中:

uint32_t unpackBits( uint8_t word[14], int startbit, int endbit )
{
    uint32_t result;
    int i;

    for (result = 0, i = endbit; i >= startbit; i--) {
        uint8_t value = (word[i/8U] & (1 << (i%8U)) != 0;
        result = (result << 1) | value;
    }
    return result;
}