首页 > 代码库 > C语言实现memcpy和memmove
C语言实现memcpy和memmove
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 s17 (2)内存低端 <-----s--<==>--d-----> 内存高端 start at end of s18 (3)内存低端 <-----sd-----> 内存高端 do nothing19 (4)内存低端 <-----d--<==>--s-----> 内存高端 start at beginning of s20 (5)内存低端 <-----d-----> <-----s-----> 内存高端 start at beginning of s21 *********************************************************************/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 end39 s = s + n - 1; // move to end40 while (n--)41 *d-- = *s--;42 }43 // (1)当源内存的首地址等于目标内存的首地址时,不进行任何拷贝44 // do nothing45 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 = http://www.mamicode.com/"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 = http://www.mamicode.com/"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
C语言实现memcpy和memmove