• strcpy()、memcpy()、memmove()、memset()的实现


    http://www.cnblogs.com/EricYang/archive/2009/09/03/1559827.html

    其实转的是两篇文章,有些交叉点故合为一篇,分别转自:

    函数简介:memmove、memcpy和memccpy简介

    函数实现:strcpy()、memcpy()、memmove()、memset()的实现

    memmove、memcpy和memccpy三个函数都是内存的拷贝,从一个缓冲区拷贝到另一个缓冲区。
    memmove(void *dest,void*src,int count)
    memcpy(void *dest,void *src,int count)
    memccpy(void*dest,void*src,int ch,int count)
    表头文件: #include <string.h>
    定义函数: void *memcpy(void *dest, const void *src, size_t n)
    函数说明: memcpy()用来拷贝src所指的内存内容前n个字节到dest所指的内存地址上。与strcpy()不同的是,memcpy()会完整的复制n个字节,不会因为遇到字符串结束'\0'而结束
    返回值:   返回指向dest的指针
    表头文件: #include <string.h>
    定义函数: void *memccpy(void *dest, const void *src, int c, size_t n);
    函数说明: memccpy()用来拷贝src所指的内存内容前n个字节到dest所指的地址上。与memcpy()不同的是,memccpy()如果在src中遇到某个特定值(int c)立即停止复制。
    返回值:   返回指向dest中值为c的下一个字节指针。返回值为0表示在src所指内存前n个字节中没有值为c的字节。
    表头文件: #include <string.h>
    定义函数: void *memmove(void *dest, const void *src, size_t n);
    函数说明:memmove()是从一个缓冲区移动到另一个缓冲区中。 
    返回值:   返回指向dest指针。
    当dest <= src-count 或dest >= src+count时,以上三个函数均不会产生覆盖问题,即源数据不会被更改。
    若不在以上范围内,则源数据会被更改。
    如:
    char a[]={'a','b'};
    char b[]={'c','d','e','f','g','h'};
    memmove(a,b,sizeof(b));
    或是直接char *p=b+2;memmove(p,b,sizeof(b));
    输出数据会发现b中数据输出已被更改。
    发现即使a数组指向的空间不够存储数据,也能够移动成功。
    原因|dest - src |<count
    如果在使用这些函数时,分配给足够的空间,然后再使用就不会出现覆盖问题。也就是说如果外部分配给的空间不足以存储要拷贝的数据时,就有可能出现源数据被覆盖更改的问题。

    #include <stdio.h> 
    #include <stdlib.h> 
    #include <string.h> 
    void main(void) 
    { 
    int i=0; 
    char a[9]={'a','b','c','d','e','f','g','h','\0'}; 
    char p[2]={'q','w'};//或char *p=a+2; 
    memmove(p,a,sizeof(a)); 
    puts(a); 
    printf("_____________________________________________\n"); 
    puts(p); 
    printf("_____________________________________________\n"); 
    for(i =0;i<10;i++) 
       printf("%c %d \n",*(a+i),a+i); 
    printf("_____________________________________________\n"); 
    for(i =0;i<8;i++) 
       printf("%c %d \n",*(p+i),p+i);  
    } 


    观察输出结果。
    把memmove(p,a,sizeof(a));改为memcpy(p,a,sizeof(a));或memccpy(p,a,'e',sizeof(a));再观察输出结果。
    可以看出在目的存储空间不足时,便会出现源数据被覆盖改变的问题。
    如果目的存储空间分配足够的空间,则便不会出现覆盖问题。

    strcpy()、memcpy()、memmove()、memset()的实现
    strcpy(), 字符串拷贝.
      2char *strcpy(char *strDest, const char *strSrc)
      3{
      4    assert((strDest!=NULL) && (strSrc !=NULL));
      5    char *address = strDest;     
      6    while( (*strDest++ = * strSrc++!= '\0'
      7       NULL ; 
      8    return address ;       
      9}

     10
     11memcpy, 拷贝不重叠的内存块 
     12void *memcpy(void* pvTo, void* pvFrom, size_t size) //byte是java里的变量类型
     13{
     14assert(pvTo != NULL && pvFrom != NULL);
     15void* pbTo = (byte*)pvTo;
     16void* pbFrom = (byte*)pvFrom;
     17/* 内存块重叠吗?如果重叠,就使用memmove */
     18assert(pbTo>=pbFrom+size || pbFrom>=pbTo+size);
     19while(size-->0)
     20    *pbTo++ == *pbFrom++;
     21return pvTo;
     22}

     23
     24void *MemCopy(void *dest,const void *src,size_t count)
     25{
     26    char *pDest=static_cast<char *>(dest);
     27    const char *pSrc=static_cast<const char *>(src);
     28    if( pDest>pSrc && pDest<pSrc+count )
     29    {
     30        for(size_t i=count-1; i<=0++i)
     31        {
     32            pDest[i]=pSrc[i];
     33        }

     34    }

     35    else
     36    {
     37        for(size_t i=0; i<count; ++i)
     38        {
     39             pDest[i]=pSrc[i];
     40        }

     41    }

     42    return pDest;
     43}

     44
     45void *Memmove(void *Dst, const void*Src,size_t count)
     46{
     47assert(Dst && Src);
     48void* pDst = Dst;
     49if (Dst<Src && (char*)Dst > (char*)Src + count)
     50{
     51while(count--)
     52{
     53   *(char*)Dst = *(char*)Src;
     54   Dst = (char*)Dst + 1;
     55   Src = (char*)Src + 1;
     56}

     57}

     58else
     59{
     60   Dst = (char*)Dst + count - 1;
     61   Src = (char*)Src + count - 1;
     62   while(count--)
     63   {
     64      *(char*)Dst = *(char*)Src;
     65      Dst = (char*)Dst -1 ;
     66      Src = (char*)Src -1 ;
     67   }

     68}

     69return pDst;
     70}

     71
     72
     73void* memmove(void *dest, const void *src,size_t n) 
     74
     75    if (n == 0return 0
     76    if (dest == NULL) return 0
     77    if (src == NULL)    return 0
     78    char *psrc = (char*)src; 
     79    char *pdest = (char*)dest; 
     80    if((dest <= psrc) || (pdest >= psrc + n)) /*检查是否有重叠问题 */ 
     81        
     82         for(int i=0; i < n; i++/*正向拷贝*/ 
     83          
     84           *pdest = *psrc; 
     85           psrc++
     86           pdest++
     87          }
     
     88        }
     
     89        else /*反向拷贝*/ 
     90        
     91          psrc += n; 
     92          pdest += n; 
     93          for(int i=0;i<n;i++
     94           
     95            psrc--
     96            pdest--
     97            *pdest = *psrc; 
     98           }
     
     99        }
     
    100   return dest;
    101}

    102
    103memset:把buffer所指内存区域的前count个字节设置成字符c
    104
    105void * Memset(void* buffer, int c, int count)
    106{
    107char* pvTo=(char*)buffer;
    108assert(buffer != NULL);
    109while(count-->0)
    110*pvTo++=(char)c;
    111return buffer;
    112}

    113

  • 相关阅读:
    《转》 在C++中使用TinyXML2解析xml
    基于多种转换语义的图数据库查询
    tomcat内存、连接数优化
    JAVA基础针对自己薄弱环节总结01(循环之前的知识)
    CodeForces
    N年的经验在别人眼里是怎么看的?
    perl install-module.pl DateTime 执行无效问题的解决
    在Linux上使用iptables命令开启对外访问的网络端口
    Linux上安装Bugzilla4.4小记
    在Lotus Notes设置邮件转发
  • 原文地址:https://www.cnblogs.com/carl2380/p/1924632.html
Copyright © 2020-2023  润新知