【问题标题】:Fastest way to convert 7-bit values into bytes将 7 位值转换为字节的最快方法
【发布时间】:2014-05-07 01:28:37
【问题描述】:

我需要以 C 语言中最快的方式将 112 位(16 字节)的 7 位值变量(它们以字节接收但 MSb 必须丢弃)转换为 14 字节。

所以基本上,我需要做的是把接收到的第一个字节的前 7 位移到左边,然后把第二个字节的第 7 位放在第一个字节中存储在位位置 0 所以我会在第一个字节中获得接收到的第一个字节的 7 位加上第二个字​​节的第 7 位。然后我将不得不对其余部分做同样的事情。

我能想到的第一个方法是:

byteToStore [0] = 1 << byteReceived[0] + byteReceived[1] & 1; 
byteToStore [1] = 2 << byteReceived[1] + byteReceived[2] & 3; 
byteToStore [2] = 3 << byteReceived[2] + byteReceived[3] & 7; 

等等。

此外,如果可以使用 for 循环轻松制作,那就太好了。我可以用我的方法使用 for 循环,但它不会那么“干净”。

谢谢。

【问题讨论】:

  • 我认为您混淆了移位操作数:移位操作数在左侧,移位宽度在右侧。此外,您最终可能会得到一个左移和右移,而不是一个移位和一个按位与。

标签: c embedded byte bits


【解决方案1】:

您想将相邻字节中的一些位打包到一个字节中。这可以通过将左字节的最低 7 位与右字节的最低 7 位相结合来实现:

void pack(const uint8_t in[16], uint8_t out[14])
{
    out[ 0] = (in[ 0] & 0x7f) << 1 | (in[ 1] & 0x7f) >> 6;
    out[ 1] = (in[ 1] & 0x7f) << 2 | (in[ 2] & 0x7f) >> 5;
    out[ 2] = (in[ 2] & 0x7f) << 3 | (in[ 3] & 0x7f) >> 4;
    out[ 3] = (in[ 3] & 0x7f) << 4 | (in[ 4] & 0x7f) >> 3;
    out[ 4] = (in[ 4] & 0x7f) << 5 | (in[ 5] & 0x7f) >> 2;
    out[ 5] = (in[ 5] & 0x7f) << 6 | (in[ 6] & 0x7f) >> 1;
    out[ 6] = (in[ 6] & 0x7f) << 7 | (in[ 7] & 0x7f) >> 0;

    out[ 7] = (in[ 8] & 0x7f) << 1 | (in[ 9] & 0x7f) >> 6;
    out[ 8] = (in[ 9] & 0x7f) << 2 | (in[10] & 0x7f) >> 5;
    out[ 9] = (in[10] & 0x7f) << 3 | (in[11] & 0x7f) >> 4;
    out[10] = (in[11] & 0x7f) << 4 | (in[12] & 0x7f) >> 3;
    out[11] = (in[12] & 0x7f) << 5 | (in[13] & 0x7f) >> 2;
    out[12] = (in[13] & 0x7f) << 6 | (in[14] & 0x7f) >> 1;
    out[13] = (in[14] & 0x7f) << 7 | (in[15] & 0x7f) >> 0;
}

虽然每个块都有一个清晰的模式,但在没有循环的情况下编写代码可能会更快,因为循环控制和移位算法不会花费任何时间。可以通过预先计算已删除所有最高有效位的辅助输入数组来加速代码,因此您不必为每个位提取最低 7 位 (x &amp; 0x7f) 两次。 (最后一次右移 0 没有任何作用,但编译器会将其优化掉。我保留它是为了对称。)

【讨论】:

  • 我曾想过类似的事情,但我一直在寻找“可扩展”的东西,因为将来我可能不得不为 192 位或更多位做同样的事情。无论如何,现在我将按照您的建议实施它。谢谢!
  • 它已经是可扩展的了:你可以调用例程pack56 并丢弃以out[7] 开头的后半部分。然后你可以拥有pack112,它调用pack56(in, out)pack56(in + 8, out + 7)。函数pack168 额外调用pack56(in + 16, out + 14)
  • 另外,正如我所说,有一个清晰的模式,您可以将逻辑滚动到更灵活的循环中。我只是认为使用硬编码索引而不是循环的变体可能会更快。不过,我还没有对此进行测试,这个假设更多地基于直觉。
  • @Twistx77 :您要求“尽可能快”,这可能与“可扩展”互斥(您将添加循环开销)。然而,“尽可能快”是一个无益的要求。足够快就足够好了。您可以通过展开隐含循环使其变快,也可以通过使用两个嵌套循环使其变小。
猜你喜欢
  • 2013-06-25
  • 2011-06-26
  • 2011-04-05
  • 1970-01-01
  • 1970-01-01
  • 2014-06-08
  • 2012-02-08
  • 1970-01-01
  • 2015-03-03
相关资源
最近更新 更多