0.二者比較:html
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.memcpyui
首先是memcpy:spa
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:.net
memcpy與memmove的目的都是將N個字節的源內存地址的內容拷貝到目標內存地址中。unix
但當源內存和目標內存存在重疊時,memcpy會出現錯誤,而memmove能正確地實施拷貝,但這也增長了一點點開銷。code
memmove的處理措施:htm
(1)當源內存的首地址等於目標內存的首地址時,不進行任何拷貝blog
(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