0.两者比较:
memmove用于从src拷贝count个字符到dest,如果目标区域和源区域有重叠的话,memmove能够保证源串在被覆盖之前将重叠区域的字节拷贝到目标区域中。但复制后src内容会被更改。但是当目标区域与源区域没有重叠则和memcpy函数功能相同。
memmove在copy两个有重叠区域的内存时可以保证copy的正确,而memcopy就不行了,但memcopy比memmove的速度要快一些,如:
char s[] = "1234567890";
char* p1 = s;
char* p2 = s+2;
memcpy(p2, p1, 5)与memmove(p2, p1, 5)的结果就可能是不同的,memmove()可以将p1的头5个字符"12345"正确拷贝至p2,而memcpy()的结果就不一定正确了。
1.memcpy
首先是memcpy:
1 #ifndef MEMCPY_H 2 #define MEMCPY_H 3 4 #include <stdio.h> 5 6 void *cat_memcpy(void *dst, const void *src, size_t n) { 7 if (NULL == dst || NULL == src) 8 return NULL; 9 10 char *d = (char *)dst; 11 const char *s = (const char *)src; 12 13 while (n--) 14 *d++ = *s++; 15 16 return dst; 17 } 18 19 #endif
2.memmove:
memcpy与memmove的目的都是将N个字节的源内存地址的内容拷贝到目标内存地址中。
但当源内存和目标内存存在重叠时,memcpy会出现错误,而memmove能正确地实施拷贝,但这也增加了一点点开销。
memmove的处理措施:
(1)当源内存的首地址等于目标内存的首地址时,不进行任何拷贝
(2)当源内存的首地址大于目标内存的首地址时,实行正向拷贝
(3)当源内存的首地址小于目标内存的首地址时,实行反向拷贝
-- memmove实现
1 #ifndef MEMMOVE_H 2 #define MEMMOVE_H 3 4 /********************************************************************* 5 memcpy与memmove的目的都是将N个字节的源内存地址的内容拷贝到目标内存地址中 6 7 但当源内存和目标内存存在重叠时,memcpy会出现错误, 8 而memmove能正确地实施拷贝,但这也增加了一点点开销。 9 10 memmove的处理措施: 11 (1)当源内存的首地址等于目标内存的首地址时,不进行任何拷贝 12 (2)当源内存的首地址大于目标内存的首地址时,实行正向拷贝 13 (3)当源内存的首地址小于目标内存的首地址时,实行反向拷贝 14 15 内存的5种情况: 16 (1)内存低端 <-----s-----> <-----d-----> 内存高端 start at end of s 17 (2)内存低端 <-----s--<==>--d-----> 内存高端 start at end of s 18 (3)内存低端 <-----sd-----> 内存高端 do nothing 19 (4)内存低端 <-----d--<==>--s-----> 内存高端 start at beginning of s 20 (5)内存低端 <-----d-----> <-----s-----> 内存高端 start at beginning of s 21 *********************************************************************/ 22 23 24 #include <stdio.h> 25 26 void *cat_memmove(void *dst, const void *src, size_t n) { 27 if (NULL == dst || NULL == src || 0 == n) 28 return NULL; 29 30 char *d = (char *)dst; 31 const char *s = (const char *)src; 32 33 34 if (s > d) { // (2)当源内存的首地址大于目标内存的首地址时,实行正向拷贝 35 while (n--) 36 *d++ = *s++; 37 } else if (s < d){ // (3)当源内存的首地址小于目标内存的首地址时,实行反向拷贝 38 d = d + n - 1; // move to end 39 s = s + n - 1; // move to end 40 while (n--) 41 *d-- = *s--; 42 } 43 // (1)当源内存的首地址等于目标内存的首地址时,不进行任何拷贝 44 // do nothing 45 46 return dst; 47 } 48 49 #endif
src和dst的内存示意图,5种情况(自己在纸上画画就很容易明白的!):
(1)内存低端 <-----s-----> <-----d-----> 内存高端 start at end of s
(2)内存低端 <-----s--<==>--d-----> 内存高端 start at end of s
(3)内存低端 <-----sd-----> 内存高端 do nothing
(4)内存低端 <-----d--<==>--s-----> 内存高端 start at beginning of s
(5)内存低端 <-----d-----> <-----s----> 内存高端 start at beginning of s
可以看到(1)、(2)处理方法一样;(4)、(5)处理方法一样。
main:测试代码:
1 #include "memcpy.h" 2 #include "memmove.h" 3 4 void test_memcpy(); 5 void test_memmove(); 6 7 int main() { 8 9 test_memmove(); 10 11 return 0; 12 } 13 14 void test_memcpy() { 15 char dst[64] = {0}; 16 char *src = "test memcpy"; 17 char *ret = (char *)cat_memcpy(dst, src, strlen(src) + 1); 18 char *ret1 = (char *)cat_memcpy(dst, src, strlen(src)); 19 printf("%s\n%s\n%s\n", ret, dst, ret1); 20 } 21 22 void test_memmove() { 23 char dst[64] = { 0 }; 24 char *src = "test cat_memmove"; 25 char *ret = (char *)cat_memmove(dst, src, strlen(src) + 1); 26 char *ret1 = (char *)cat_memmove(dst, src, strlen(src)); 27 printf("%s\n%s\n%s\n", ret, dst, ret1); 28 29 printf("\n====================================\n[src<dst]:\n"); 30 char s[] = "1234567890"; 31 char* p1 = s; 32 char* p2 = s + 2; 33 char *sRet = (char *)cat_memmove(p2, p1, 5); 34 printf("memmove:\n%s\n%s\n%s\n\n", sRet, p1, p2); 35 36 char s1[] = "1234567890"; 37 char* p11 = s1; 38 char* p22 = s1 + 2; 39 char *sRet1 = (char *)cat_memcpy(p22, p11, 5); 40 printf("memcpy:\n%s\n%s\n%s\n", sRet1, p11, p22); 41 42 printf("\n====================================\n[src>dst]:\n"); 43 char ss[] = "1234567890"; 44 char* pp1 = ss; 45 char* pp2 = ss + 2; 46 char *ssRet = (char *)cat_memmove(pp1, pp2, 5); 47 printf("memmove:\n%s\n%s\n%s\n\n", ssRet, pp1, pp2); 48 49 char ss1[] = "1234567890"; 50 char* pp11 = ss1; 51 char* pp22 = ss1 + 2; 52 char *ssRet1 = (char *)cat_memcpy(pp11, pp22, 5); 53 printf("memcpy:\n%s\n%s\n%s\n", ssRet1, pp11, pp22); 54 }
ref:
http://www.cnblogs.com/kekec/archive/2011/07/22/2114107.html
http://blog.chinaunix.net/uid-22780578-id-3346391.html