2012-11-12 48 views
10

从Linux联机帮助页memmove(3)为什么Linux memmove()以这种方式实现?

的的memmove()函数拷贝n个字节从存储器区域的src到存储器区域DEST。 存储区可能重叠:复制发生,就好像src中的字节是 首先被复制到与src或dest不重叠的临时数组中,然后 字节从临时数组复制到dest。

不是分配一个临时数组复制值的两倍,我们可能只是做到以下几点:

void *my_memmove(void *dest, const void *src, size_t n) { 
    signed char operation; 
    size_t end; 
    size_t current; 

    if(dest != src) { 
    if(dest < src) { 
     operation = 1; 
     current = 0; 
     end = n; 
    } else { 
     operation = -1; 
     current = n - 1; 
     end = -1; 
    } 

    for(; current != end; current += operation) { 
     *(((unsigned char*)dest) + current) = *(((unsigned char*)src) + current); 
    } 
    } 
    return dest; 
} 

在此实现,我们只是拿我们开始复制位置的照顾。

我的实施有没有缺点?

注意:我不会实际使用我的实现。我只是好奇。

+4

当dest和src指向不同的块时,dest 是未定义的行为。当'dest'和'src'指向同一个块时,函数'memmove()'被指定为工作,但没有指定它必须用指向同一个块的指针来调用。看到相关的问题http://stackoverflow.com/questions/4023320/how-to-implement-memmove-in-standard-c-without-an-intermediate-copy –

+12

我想你错过了“好像”在手册页。它实际上并不这样。 – dbrank0

+0

您可以将您的实现与[FreeBSD的'bcopy'](http://fxr.watson.org/fxr/source/string/bcopy.c?v=FREEBSD-LIBC),它们的memmove()的底层代码进行比较。它也支持向后复制,没有临时缓冲区。 – ShiDoiSi

回答

22

你可以看一些源代码的memmove herehereherehere

你会注意到的是,他们不会实际上做一个临时数组。写手册页是为了帮助你理解它在做什么逻辑上,而不是实际上。因此,他们说“好像”。

什么的memmove()实际上做的是字节复制从srcdest,并将其复制着,如果dest < src(这基本上是同样的事情的memcpy),并且向后否则。

memcpymemmove之间的区别是,memcpy盲目拷贝前锋 - 这就是为什么destsrc不能重叠。但memmove采取预防措施,确保重叠不会搞砸最终结果。

+2

优秀点。 Linux memmove的C源代码是[here](http://sourceware.org/git/?p=glibc.git;a=blob;f=string/memmove.c;h=bf7dcc162770503ed62a262f627bfa526fc5a0d7;hb=HEAD),但它在很大程度上是不相关的,因为实际的'memmove'实现了[手动优化程序集](http://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/x86_64/memcpy.S; h = 9e693f2a9806fa8f6ce7e26f37b1808e952396d3; hb = HEAD),它绝对不会复制到临时数组。作为好奇心,它的定义与'memcpy'完全相同,因为在其目标架构中,这样做不会有任何处罚。 – user4815162342

相关问题