如何从不在字节对齐(偏移)的源中复制内存

5

我能想到一些低效的方法来完成这个任务,但我想知道最好的方法是什么。

例如,我想复制从字节中的第3位开始的10个字节,并像往常一样复制到指针中。

有没有比一次复制一个移位字节更好的方法?

谢谢。


就像 @SamB说的一样。我正在使用一种低内存系统,并且有一些紧密打包的数据。即使它没有意义,我还是觉得问一下问题。 - Ryu
4
请看这个非常相似的问题:https://dev59.com/8E_Ta4cB1Zd3GeqPE-3v - nategoose
@nategoose 谢谢!我尝试搜索看看是否已经有人问过这个问题,但是没有找到任何相关信息。 - Ryu
3个回答

5
一般的方法是尽可能高效地读取源缓冲区,并在写入目标缓冲区时根据需要进行移位。
你不必进行字节操作,你可以通过在开始时执行最多三个字节,并类似地处理结尾,使得源读取long对齐以进行大部分操作。
从读取的值中,您根据需要进行移位,以获得所需的位对齐,并组装完成的字节以写入目标。您也可以将写入优化为最宽对齐的字大小。
如果您深入研究使用可变宽度标记的压缩工具或库(例如zlib、MPEG、TIFF和JPEG),您可能会找到将输入或输出缓冲区视为一系列位的示例代码,这将有一些实现思路供您参考。

3

在x86架构中,你可以访问的最小单元是一个字节。然而,你可以一次性访问4个字节,并且可以同时处理4个字节而不是一个字节。为了获得更快的速度,你可以使用pslldq (SSE2)。当然,确保你的拷贝对齐以获得最大的性能。


1
与提问者想要的无关。他想要复制具有子字节对齐的数据,而你只是告诉他如何实现比他已经拥有的更糟糕的memcpy - SamB
2
@SamB:其实并不是这样。整个字一次性进行比特移位的速度要比逐个字节移位快得多。 - R.. GitHub STOP HELPING ICE
是的 - @R 是正确的。快了很多。你可以看每指令周期数。让我们不要草率下结论。 - EdH

0

这是我编写的解决方案,并开始使用。

void RightShiftMemCopy(uchar * pSource, uchar * pDest ,ushort len,uchar shiftOffset)
{
    ushort i=0;

    pDest+=(len-1);
    pSource+=(len-1);

    for(i=len-1;i != 0 ;--i)
    {
        *pDest = (*(pSource - 1) << 8 | *pSource) >> shiftOffset;

        --pDest;
        --pSource;
    }

    *pDest = *pSource >> shiftOffset;

}

不要调用 memcpy() 来复制一个字节。只需使用 destData[i] = val。你在这里使用的 pSource 是一个糟糕的命名选择。而且它在 memcpy 调用中的使用假定了特定的字节序。 - RBerteig

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接