Bitwise memmove

时间:2013-09-14 16:05:23

标签: c bit-manipulation bitset memmove

实现按位memmove的最佳方法是什么?该方法应该采用额外的目标和源位偏移,计数也应该是位。

  • 我看到ARM提供了一个非标准的_membitmove,它正是我所需要的,但我找不到它的来源。
  • Bind的bitset包含isc_bitstring_copy,但效率不高
  • 我知道C标准库没有提供这样的方法,但我也找不到提供类似方法的任何第三方代码。

3 个答案:

答案 0 :(得分:1)

由于Highlevel语言提供的最小单位为1 Byte,因此没有标准函数可以为您提供此选项。也许您可以寻找提供此类功能的第三方库,但否则您必须自己编写代码。

答案 1 :(得分:1)

这是部分实现(未测试)。有明显的效率和可用性改进。

n字节从src复制到dest(不重叠src),并将dest向右移位bit位, 0< = bit< = 7.这假设最低有效位在字节的右边

void memcpy_with_bitshift(unsigned char *dest, unsigned char *src, size_t n, int bit)
{
  int i;

  memcpy(dest, src, n);

  for (i = 0; i < n; i++) {
    dest[i] >> bit;
  }

  for (i = 0; i < n; i++) {
    dest[i+1] |= (src[i] << (8 - bit));
  }
}

要做出一些改进:

  • 请勿在{{1​​}}开头覆盖第一个bit位。
  • 合并循环
  • 有办法复制一些不能被8整除的位。
  • 在char
  • 中修复&gt; 8位

答案 2 :(得分:1)

假设“最佳”意味着“最简单”,您可以逐个复制位。从概念上讲,位的地址是一个对象(struct),它有一个指向内存中字节的指针和一个字节中位的索引。

struct pointer_to_bit
{
    uint8_t* p;
    int b;
};

void membitmovebl(
    void *dest,
    const void *src,
    int dest_offset,
    int src_offset,
    size_t nbits)
{
    // Create pointers to bits
    struct pointer_to_bit d = {dest, dest_offset};
    struct pointer_to_bit s = {src, src_offset};

    // Bring the bit offsets to range (0...7)
    d.p += d.b / 8; // replace division by right-shift if bit offset can be negative 
    d.b %= 8; // replace "%=8" by "&=7" if bit offset can be negative
    s.p += s.b / 8;
    s.b %= 8;

    // Determine whether it's OK to loop forward
    if (d.p < s.p || d.p == s.p && d.b <= s.b)
    {
        // Copy bits one by one
        for (size_t i = 0; i < nbits; i++)
        {
            // Read 1 bit
            int bit = (*s.p >> s.b) & 1;

            // Write 1 bit
            *d.p &= ~(1 << d.b);
            *d.p |= bit << d.b;

            // Advance pointers
            if (++s.b == 8)
            {
                s.b = 0;
                ++s.p;
            }
            if (++d.b == 8)
            {
                d.b = 0;
                ++d.p;
            }
        }
    }
    else
    {
        // Copy stuff backwards - essentially the same code but ++ replaced by --
    }
}

如果你想编写一个针对速度优化的版本,你将不得不按字节(或更好,单词)进行复制,展开循环,并处理一些特殊情况(memmove这样做;你将需要做更多,因为你的功能更复杂。)

P.S。哦,看到你调用isc_bitstring_copy效率低下,你可能想要速度优化。您可以使用以下想法:

单独开始复制位,直到目标字节对齐(d.b == 0)。然后,很容易一次复制8位,做一些小事。这样做直到剩下少于8位要复制;然后继续逐个复制位。

// Copy 8 bits from s to d and advance pointers
*d.p = *s.p++ >> s.b;
*d.p++ |= *s.p << (8 - s.b);

P.P.S哦,看到你对将要使用代码的评论,你真的不需要实现所有的版本(byte / halfword / word,big / little-endian);你只想要最简单的一个 - 使用单词(uint32_t)。