在不复制源数据的情况下实现 memmo

时间:2021-01-20 06:22:53

标签: c memmove

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

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

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

谢谢!

2 个答案:

答案 0 :(得分:3)

memmove 的描述说明

<块引用>

复制发生就好像首先将s2指向的对象的n个字符复制到n个字符的临时数组中,该数组不与s1和s2指向的对象重叠,然后将临时数组中的 n 个字符复制到 s1 指向的对象中。

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

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

如果你逐字符复制,你可以检查哪个指针首先出现在内存中,即如果target > source意味着你需要反向复制,即从n - 1和向后复制。

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

考虑到警告,您可以将两者都转换为 uintptr_t 进行比较并希望最好(并担心最坏)。我相信转换为 uintptr_t 在 x86 实模式下不起作用(即“640 KB 对任何人来说都足够了”模式),但无论如何谁都想为它编程。

答案 1 :(得分:0)

希望以下代码可以帮助您:

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