zoukankan      html  css  js  c++  java
  • 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 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
    %s
    %s
    ", 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
    %s
    %s
    ", ret, dst, ret1);
    28 
    29     printf("
    ====================================
    [src<dst]:
    ");
    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:
    %s
    %s
    %s
    
    ", 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:
    %s
    %s
    %s
    ", sRet1, p11, p22);
    41 
    42     printf("
    ====================================
    [src>dst]:
    ");
    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:
    %s
    %s
    %s
    
    ", 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:
    %s
    %s
    %s
    ", 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

  • 相关阅读:
    windows利用net use删除smb连接
    用jquery的ajax功能获取网站alexa的方法
    11对于Web开发人员和设计师非常有用的在线工具
    Php获取Alexa排行统计
    php获取alexa世界排名值的函数
    26个免费矢量图片免费下载
    对makefile中双冒号规则的学习
    对makefile中 $*的理解
    GNU make manual 翻译(七十三)
    对makefile 中的 静态模式规则的理解
  • 原文地址:https://www.cnblogs.com/lingshaohu/p/3961665.html
Copyright © 2011-2022 走看看