一,原型

void * memcpy ( void * destination, const void * source, size_t num );

功能:将以source作为起始地址的数据复制num个字节到以destination为起始地址的数据中,不支持destination和source重叠的情况。函数返回destination指针。

  1. void* memcpy (void* destination,constvoid* source,size_t num )
  2. {
  3.   char* pdes =(char*)destination;
  4.   char* psrc =(char*)source;
  5.   assert(destination !=NULL && source !=NULL && num>);
  6.   while(num--)
  7.     *pdes++=*psrc++;
  8.   return destination;
  9. }
 
void * memmove ( void * destination, const void * source, size_t num );
功能:将以source作为起始地址的数据的num个字节移动到以destination为起始地址的数据中,支持destination和source重叠的情况。函数返回destination指针。
  1. void* memmove (void* destination,constvoid* source,size_t num )
  2. {
  3.   char* pdes =(char*)destination;
  4.   char* psrc =(char*)source;
  5.   assert(destination !=NULL && source !=NULL && num>);
  6.   //判断destination和source是否存在重叠
  7.   if(pdes+num <psrc || psrc+num < pdes)//不存在重叠,正常从前向后复制
  8.     while(num--)
  9.       *pdes++=*psrc++;
  10.   else//存在重叠,防止信息丢失,从后向前复制
  11.   {
  12.     pdes = pdes+num-;
  13.     psrc = psrc+num-;
  14.     while(num--)
  15.       *pdes--=*psrc--;
  16.   }
  17.   return destination;
  18. }
 
void * memset ( void * ptr, int value, size_t num );
功能:将以ptr作为起始地址的数据的num个字节设置为value。函数返回destination指针。
  1. void* memset (void* ptr,int value,size_t num )
  2. {
  3.   char* ptmp =(char*)ptr;
  4.   assert(ptr !=NULL && num >);
  5.   while(num--)
  6.     *ptmp++= value;
  7.   return ptr;
  8. }
 
int memcmp ( const void * ptr1, const void * ptr2, size_t num );
功能:比较以ptr1为起始地址数据和以ptr2为起始地址的数据的num个字节大小情况。如果num个字节都相等,则相等,函数返回0。从起始位置开始,如果某个字节大,则prt1>ptr2,函数返回正数,否则ptr<ptr2,函数返回负数。

  1. int memcmp (const void* ptr1,const void* ptr2,size_t num )
  2. {
  3.   int ret =;
  4.   const char* ptmp1 =(char*)ptr1;
  5.   const char* ptmp2 =(char*)ptr2;
  6.   assert(ptr1 != NULL && ptr2 != NULL && num>);
  7.   while(num--)
  8.   {
  9.     if(*ptmp1 >*ptmp2)
  10.     {
  11.       ret =;
  12.       break;
  13.     }
  14.     if(*ptmp1 <*ptmp2)
  15.     {
  16.       ret =-;
  17.       break;
  18.     }
  19.     ptmp1++;
  20.     ptmp2++;
  21.   }
  22.   return ret;
  23. }
 
void * memchr (void * ptr, int value, size_t num ); 
功能:在以ptr作为起始地址的数据中的num个字节中查找value,如果查到,则返回value所在的地址,否则返回NULL。
  1. void* memchr (void* ptr,int value,size_t num )
  2. {
  3.   char* pret = NULL;
  4.   char* ptmp =(char*)ptr;
  5.   assert(ptr !=NULL && num>);
  6.   while(num)
  7.   {
  8.     if(*ptmp == value)
  9.     {
  10.       pret = ptmp;
  11.       break;
  12.     }
  13.     ptmp++;
  14.     num--;
  15.   }
  16.   return pret;
  17. }

二,详解

memcpy函数详解

void *memcpy( void *dest, const void *src, size_t count );

作用:

  在dest处拷贝src处的字节,并以count来计算需要拷贝的字节数量,进行内存的拷贝。

参数:

  dest:新的存贮区的开始部位

  src:需要拷贝的开始部位

  count:需要拷贝的字节数

备注:

  dest,src,它们都是从各自的地址处进行写入,如果是p而不是&p,那么将会取得p的值(地址),在该值的地址处进行读出或写入。

例:

  1. int* intPoint = new int();
  2.  
  3. int* intPoint1;
  4.  
  5. memcpy( &intPoint1, &intPoint, );//在intPoint1的地址处写入intPoint地址处的值,也就是intPoint指针值。
  6.  
  7. cout << *intPoint1 << endl; //使intPoint1指向了intPoint.

  1. int* intPoint = new int();
  2.  
  3. int intPoint1;
  4.  
  5. memcpy( &intPoint1, intPoint, );
  6.  
  7. cout << intPoint1 << endl;

2)

memcpy函数的实现与应用

memcpy函数较memmove相比,存在的不足是没有考虑到目的地址与源地址相重合,本文对memcpy作了修改,弥补其不足。

memcpy函数的特点是:

1. 使用memcpy函数前,实参dest必须初始化,否则可能会出错,原因见2。

2. 函数原理是将void *src 强制转换为char *s,然后只负责拷贝n个字节到dest里,不负责在最后加上'\0'。

下面的代码其实是实现了memmove的功能,然后根据memcpy的参数为void*,给其分别尝试传入int*和char*,以此来掌握int*是如何转化为char*,及强制转化后是什么结果,涉及到大端和小端等等。

  1. #include <stdio.h>
  2. #include <string.h>
  3. void * mymemcpy(void *dest,void *src, int n)
  4. {
  5. char *d;
  6. char *s;
  7. int i=;
  8.  
  9. s=(char *)src;
  10. d=(char *)dest;
  11. if(dest==NULL || src==NULL || n<)
  12. return ;
  13. if(d>=s && d<=s+n-)
  14. {
  15. i=n-;
  16. printf("%d\n",i);
  17. while(i>=)
  18. {
  19. d[i]=s[i];
  20. i--;
  21. }
  22. }
  23. else
  24. {
  25. while(i<n)
  26. {
  27. //printf("%x ",s[i]);
  28. d[i]=s[i];
  29. //printf("i=%d %x\n",i,d[i]);
  30. i++;
  31. }
  32. d[i]='\0';
  33. }
  34. dest=(void *)d;
  35. return dest;
  36. }
  37.  
  38. int main(char **argv,int argc)
  39. {
  40. //情况1
  41. char src[]="helloworldhui";
  42. //如果是特殊情况mymemcpy(src+2,src,7);,则不可写成char *src="helloworld"; 因为文字常量区内容不可被改变
  43. //char dest[100]=""; //必须初始化
  44. char *dest;
  45. dest=(char *)mymemcpy(src+,src,);
  46. printf("%s\n",dest);//*/
  47.  
  48. //情况2
  49. /* int src=123456789 ; //对应十六进制:75BCD15
  50. int dest=0;
  51. //dest必须初始化,不然,如果只拷贝3个字节时,dest的第四个字节未被赋值,这样输出会出错。
  52. memcpy(&dest,&src,3); //只能传递参数4,不然出错
  53. //mymemcpy(&dest,&src,3) //则拷贝前3个字节
  54. printf("dest=%d %x\n",dest,dest);//*/
  55.  
  56. //情况3
  57. /* int src[100]={1234,12345,123456,11234567,14,15};
  58. int dest[100]={0};
  59. int i;
  60. memcpy(dest,src,13); //只拷贝13个字节
  61. //不能保证拷贝一个完整的整数,一个元素,即如果你输入13,3*4=12,只能保证前3个整数完整拷贝,
  62. //到了第4个整数,只拷贝它的第一个字节,如例为7
  63. //mymemcpy(dest,src,13);
  64. for( i=0;i< 5;i++)
  65. printf("*%d*\n",dest[i]);//*/
  66. return ;
  67. }
  68. // 为情况3的输出结果:
  69.  
  70. #include <stdio.h>
  71. int main(void)
  72. {
  73. // int src[10]={50,61,72,83,94};
  74. _int64 src=; //0x75BCD15,它在内存中的存放从低地址,低字节开始:15,cd,5b,7
  75. char *p;
  76. int count;
  77.  
  78. p=(char *)(&src);
  79. for(count=; count<sizeof(int);p++,count++)
  80. printf("第%d字节处十六进制值是: %02x\n",count,*p);
  81. return ;
  82. }
 

C-基础:memcpy、memset、memmove、memcmp、memchr的更多相关文章

  1. 41.内存函数实现(memcpy,memset,memmove,memicmp,memchr.memccpy)

    memcpy #include <stdio.h> #include <stdlib.h> #include <memory.h> void * mymemcpy( ...

  2. memcpy、memmove、memset、memchr、memcmp、strstr详解

    第一部分 综述 memcpy.memmove.memset.memchr.memcmp都是C语言中的库函数,在头文件string.h中.memcpy和memmove的作用是拷贝一定长度的内存的内容,m ...

  3. memcpy、memmove、memset及strcpy函数实现和理解

    memcpy.memmove.memset及strcpy函数实现和理解 关于memcpy memcpy是C和C++ 中的内存拷贝函数,在C中所需的头文件是#include<string.h> ...

  4. strcpy()、memcpy()、memmove()、memset()的内部实现

    一直想知道 strcpy().memcpy().memmove().memset()的内部实现 strcpy(), 字符串拷贝. char *strcpy(char *strDest, const c ...

  5. 不使用库函数、自己编写的(strlen、strcpy、strcmp、strcat、memcmp、memcpy、memmove)

    不使用库函数.自己编写的(strlen.strcpy.strcmp.strcat.memcmp.memcpy.memmove) //求字符串长度的函数 int my_strlen(const char ...

  6. 关于memcpy和memmove的一点说明

    今天看到书上降到memcpy和memmove的区别才突然发现原来两者之间有如此区别,以前只知道这两个函数是 实现同样的功能,没有接触到其不同. memcpy和memmove在MSDN的定义如下: 从两 ...

  7. memcpy vs memmove

    [本文连接] http://www.cnblogs.com/hellogiser/p/memcpy_vs_memmove.html [分析] memcpy与memmove的目的都是将N个字节的源内存地 ...

  8. memcpy与memmove的区别

    在面试中经常会被问道memcpy与memove有什么区别? 整理如下: 其实主要在考C的关键字:restrict C库中有两个函数可以从一个位置把字节复制到另一个位置.在C99标准下,它们的原型如下: ...

  9. C语言实现memcpy和memmove

    0.两者比较: memmove用于从src拷贝count个字符到dest,如果目标区域和源区域有重叠的话,memmove能够保证源串在被覆盖之前将重叠区域的字节拷贝到目标区域中.但复制后src内容会被 ...

  10. 第 16 章 C 预处理器和 C 库(string.h 库中的 memcpy() 和 memmove())

    /*----------------------------------------- mems.c -- 使用 memcpy() 和 memmove() ---------------------- ...

随机推荐

  1. ORA-01843: not a valid month 错误

    转自:https://blog.csdn.net/jetluning/article/details/48785599 insert into ......的场合发生ORA-01843: not a ...

  2. Programming With Objective-C---- Encapsulating Data ---- Objective-C 学习(三) 封装数据

      Programming with Objective-C Encapsulating Data In addition to the messaging behavior covered in t ...

  3. sscanf非常的重要

    刚进研究生阶段,发现曾经学习的c语言真的好少好少,很少能够看见scanf printf等..... 以后实验的80%以上都是在linux下面 老师让我看看关于一个日志会聚的一个项目模块 发现基本上都是 ...

  4. 任务48:Identity MVC:Model后端验证

    任务48:Identity MVC:Model后端验证 RegisterViewModel using System; using System.Collections.Generic; using ...

  5. JDK8 Lamdba表达式转换成Map,value为null问题

    // 将list转换成Map类型 Map<String, String> map = list.stream().collect(Collectors.toMap(Person::getI ...

  6. poj1651【区间DP·基础】

    题意: 给你一串数字,头尾不能动,每次取出一个数字,这个数字贡献=该数字与左右相邻数字的乘积,求一个最小值. 思路: 用dp[s][t]去代表s到t的最小值,包括a[s]和a[t],然后从区间为3开始 ...

  7. PTA 朋友圈【并查集的合并问题】

    一开始,考虑的是每次就是把第一个作为祖先,这样很明显是错误的,比如 7 4 3 1 2 3 2 4 2 3 5 6 7 1 6 所以这正是更好地体现对于集合的代表.只有把所有的元素合并一下,然后选一个 ...

  8. python __builtins__ staticmethod类 (64)

    64.'staticmethod', 返回静态方法 class staticmethod(object) | staticmethod(function) -> method | | Conve ...

  9. MAC下如何配置Android手机调试(将测试手机加入到Mac系统的调试列表中)

    第一步: 查看usb设备信息 在 终端输入:system_profiler SPUSBDataType     可以查看连接的usb设备的信息 比如我的usb信息如下(部分内容): 查看到我的Andr ...

  10. Python 爬虫面试题 170 道:2019 版

    引言 最近在刷面试题,所以需要看大量的 Python 相关的面试题,从大量的题目中总结了很多的知识,同时也对一些题目进行拓展了,但是在看了网上的大部分面试题不是很满意,一个是有些部分还是 Python ...