C語言實現memcpy和memmove

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

http://blog.chinaunix.net/uid-22780578-id-3346391.html

相關文章
相關標籤/搜索