一,原型

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

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

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

int memcmp (const void* ptr1,const void* ptr2,size_t num )
{
  int ret =;
  const char* ptmp1 =(char*)ptr1;
  const char* ptmp2 =(char*)ptr2;
  assert(ptr1 != NULL && ptr2 != NULL && num>);
  while(num--)
  {
    if(*ptmp1 >*ptmp2)
    {
      ret =;
      break;
    }
    if(*ptmp1 <*ptmp2)
    {
      ret =-;
      break;
    }
    ptmp1++;
    ptmp2++;
  }
  return ret;
}
 
void * memchr (void * ptr, int value, size_t num ); 
功能:在以ptr作为起始地址的数据中的num个字节中查找value,如果查到,则返回value所在的地址,否则返回NULL。
void* memchr (void* ptr,int value,size_t num )
{
  char* pret = NULL;
  char* ptmp =(char*)ptr;
  assert(ptr !=NULL && num>);
  while(num)
  {
    if(*ptmp == value)
    {
      pret = ptmp;
      break;
    }
    ptmp++;
    num--;
  }
  return pret;
}

二,详解

memcpy函数详解

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

作用:

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

参数:

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

  src:需要拷贝的开始部位

  count:需要拷贝的字节数

备注:

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

例:

int* intPoint = new int(); 

int* intPoint1; 

memcpy( &intPoint1, &intPoint,  );//在intPoint1的地址处写入intPoint地址处的值,也就是intPoint指针值。

cout << *intPoint1 << endl;          //使intPoint1指向了intPoint.

int* intPoint = new int(); 

int intPoint1; 

memcpy( &intPoint1, intPoint,  ); 

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*,及强制转化后是什么结果,涉及到大端和小端等等。

#include <stdio.h>
#include <string.h>
void * mymemcpy(void *dest,void *src, int n)
{
char *d;
char *s;
int i=; s=(char *)src;
d=(char *)dest;
if(dest==NULL || src==NULL || n<)
return ;
if(d>=s && d<=s+n-)
{
i=n-;
printf("%d\n",i);
while(i>=)
{
d[i]=s[i];
i--;
}
}
else
{
while(i<n)
{
//printf("%x ",s[i]);
d[i]=s[i];
//printf("i=%d %x\n",i,d[i]);
i++;
}
d[i]='\0';
}
dest=(void *)d;
return dest;
} int main(char **argv,int argc)
{
//情况1
char src[]="helloworldhui";
//如果是特殊情况mymemcpy(src+2,src,7);,则不可写成char *src="helloworld"; 因为文字常量区内容不可被改变
//char dest[100]=""; //必须初始化
char *dest;
dest=(char *)mymemcpy(src+,src,);
printf("%s\n",dest);//*/ //情况2
/* int src=123456789 ; //对应十六进制:75BCD15
int dest=0;
//dest必须初始化,不然,如果只拷贝3个字节时,dest的第四个字节未被赋值,这样输出会出错。
memcpy(&dest,&src,3); //只能传递参数4,不然出错
//mymemcpy(&dest,&src,3) //则拷贝前3个字节
printf("dest=%d %x\n",dest,dest);//*/ //情况3
/* int src[100]={1234,12345,123456,11234567,14,15};
int dest[100]={0};
int i;
memcpy(dest,src,13); //只拷贝13个字节
//不能保证拷贝一个完整的整数,一个元素,即如果你输入13,3*4=12,只能保证前3个整数完整拷贝,
//到了第4个整数,只拷贝它的第一个字节,如例为7
//mymemcpy(dest,src,13);
for( i=0;i< 5;i++)
printf("*%d*\n",dest[i]);//*/
return ;
}
// 为情况3的输出结果: #include <stdio.h>
int main(void)
{
// int src[10]={50,61,72,83,94};
_int64 src=; //0x75BCD15,它在内存中的存放从低地址,低字节开始:15,cd,5b,7
char *p;
int count; p=(char *)(&src);
for(count=; count<sizeof(int);p++,count++)
printf("第%d字节处十六进制值是: %02x\n",count,*p);
return ;
}
 

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. lightoj 1125【01背包变性】

    题意: 从n个数里选出m个来,还要使得这m个数之和被d整除. 给一个n和q,再给n个数,再给q个询问,每个询问包含两个数,d,m; 对于每个case输出每个q个询问的可行的方案数. 思路: 每个数只能 ...

  2. hdoj【1006】【未完待续】

    题意: 时钟的三个指针在两两之间至少D°的时候是开心的,求开心时间占一天的一个百分比. 思路: 我们看到这个百分比有三位小数,精度很高. 一天有24h,24*60min,24*60*60s,那么最小单 ...

  3. hdoj1078【DP·记忆化搜索】

    还是满水的一道题目吧...这个一看肯定要搜索了..然后又是这么DP,那就是记忆化搜索了...走K步,下一步要比他多...很好写啊/// #include<iostream> #includ ...

  4. LuoguP1342请柬 【最短路/建反图】By cellur925

    题目传送门 开始就想直接正向跑一遍Dij把到各点的最短路加起来即可,后来发现与样例少了些,于是再读题发现需要也求出学生们回来的最短路. 但是注意到本题是有向图,如果是无向图就好说. 那么我们怎么解决? ...

  5. Django使用dwebsocket来通信,服务器报错[Error 10038]

    记录这次Django踩得最大的一次坑,没有之一.前前后后困扰了一周. 在使用Django的dwebsocket模块建立websocket时,不管是前端主动关闭,还是页面刷新,还是页面关闭.服务端均会报 ...

  6. SSM报错:No converter found for return value of type: class java.util.ArrayList at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverter

    我使用的是SSM框架,是在编写测试RESTFUL接口的时候出现, @RequestMapping(value = "/selectAll", method = RequestMet ...

  7. Win10各个版本免费激活密钥

      专业版:W269N-WFGWX-YVC9B-4J6C9-T83GX 企业版:NPPR9-FWDCX-D2C8J-H872K-2YT43 家庭版:TX9XD-98N7V-6WMQ6-BX7FG-H8 ...

  8. macOS 将【允许从以下位置下载的应用】设置为:任意来源

    用管理员帐号进入Terminal: 1) 输入:sudo spctl --master-disable ,回车: 2) 重新进入该设置页面即可看到已生效:

  9. 利用uiautomator实现Android移动app启动时间的测试

    为了减少因手工测试的反应误差,这里介绍下如何利用Android自带的自动化测试工具uiautomator实现app启动时间的测试. 测试基本思路如下: 1.启动前记录当前的时间戳 2.启动app,直至 ...

  10. C#将excel数据按照需求导入Sql server遇到的问题(参考而已)

    1.千万不要使用永中表格(WPS没用过,这里只是个人观点,不是说永中表格的) 我在公司得到的任务是将excel数据按照需求导入数据库总共主表大概3张,所以有点复杂(列子用的简单表,公司东西还是不要放出 ...