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

时间:2017-07-10 18:33:13

标签: c bitwise-operators

我正在编写一些代码,我需要编码/解码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);
}

难以编写,但如果您想要阅读/排除故障,则完全无法识别。我还没有尝试过通用的解决方案,但我觉得它会成为一个怪物。

您如何建议对晦涩的字大小进行逐位操作?

1 个答案:

答案 0 :(得分:3)

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

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;
}