在不复制源数据的情况下实施 memmove

implementing memmove without copying the source data

我需要自己实现标准的 c 函数 memmove。

void *memmove(void *str1, const void *str2, size_t n)

我可以避免在进行实际复制之前将源(由 str2 指向)复制到临时缓冲区吗?

谢谢!

memmove的描述说

Copying takes place as if the n characters from the object pointed to by s2 are first copied into a temporary array of n characters that does not overlap the objects pointed to by s1 and s2, and then the n characters from the temporary array are copied into the object pointed to by s1.

现在,“好像”部分告诉我们,这只是用来解释可观察到的行为,而不是实现实际上必须这样做的方式。

但有趣的事实是:在大多数情况下,如果不将整个源代码复制到临时缓冲区,实际上不可能在可移植标准 C 中实现 memmove (如果 src == dest,你可以完全避免复制)。

如果你逐个字符复制,你可以检查哪个指针在内存中最先出现,即如果target > source意味着你需要反向复制,即从[=14=开始] 并向后复制。

需要注意的是,如果两个指针都指向同一个数组的成员,则使用 target > source 严格符合 只有 。这不仅仅是理论上的 - 例如,x86 实模式分段内存模型会使指针比较变得困难。

考虑到警告,您可以将两者都投射到 uintptr_t 进行比较,并抱最好的希望(并担心最坏的情况)。我相信转换为 uintptr_t 不会在 x86 实模式下工作(即“640 KB 对任何人来说应该足够了”模式),但谁愿意为它编程呢。

希望以下代码对您有所帮助:

typedef unsigned char uint8_t;

typedef unsigned int uint32_t;

typedef uint32_t size_t;

void * memmove(void *dst, const void *src, size_t len){
    uint8_t *dp = (uint8_t *)dst;
    const uint8_t *sp = (const uint8_t *)src;
    
    if(sp < dp && sp + len > dp){
        sp += len;
        dp += len;
        while(len-- > 0){
            *--dp = *--sp;
        }
    }else{
        while(len-- > 0){
            *dp++ = *sp++;
        }
    }
    
    return dst;
}