一、memcpy 内存拷贝函数
函数描述:void * memcpy ( void * destination, const void * source, size_t num )
功能: 从存储区 source复制 n 个字符到存储区 destination。
参数:
- destination-- 指向用于存储复制内容的目标数组,类型强制转换为 void* 指针。
- source-- 指向要复制的数据源,类型强制转换为 void* 指针。
- num – 要被复制的字节数。
返回值:
该函数返回一个指向目标存储区 destination的指针。
注意:
- 函数memcpy从source的位置开始向后复制num个字节的数据到destination的内存位置。
- 这个函数在遇到 ‘\0’ 的时候并不会停下来。
- 如果source和destination有任何的重叠,复制的结果都是未定义的。
使用示例:
#include<stdio.h>
#include<string.h>
struct{
char name[40];
int age;
}person,person_copy;
int main()
{
char myname[]="Poerre de Fermat";
//用memcpy拷贝字符串举例
memcpy(person.name,myname,strlen(myname)+1);
person.age= 46;
//用memcpy拷贝结构体
memcpy(&person_copy,&person,sizeof(person));
printf("person_copy: %s,%d\n",person_copy.name,person_copy.age);
return 0;
}
结果:
memcpy的模拟实现:
代码如下:
void* my_memcpy(void* desc,void* src,size_t count)
{
void* ret=desc;
while(count--)
{
*(char*)desc=*(char*)src;
desc=(char*) desc+1;
src=(char*) src+1;
}
return ret;
}
二、memmove函数
函数描述:void * memmove ( void * destination, const void * source, size_t num );
**功能:**由src所指内存区域复制count个字节到dest所指内存区域。
说明:
返回值:返回指向destination的指针
- 和memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的。
- 如果源空间和目标空间出现重叠,就得使用memmove函数处理
int main()
{
char str[]="memmove can be very useful......";
memmove(str+20,str+15,11);
puts(str);
}
结果:
memmove的模拟实现:
分析:
int arr[6] = {1,2,3,4,5,6};
将数组前4个元素复制到后4个元素上,即将数组变为
{1,2,1,2,3,4}
将数组还原为初始在将后四个元素复制到三个元素上,即为
{3,4,3,4,5,6}
直接使用memcpy函数:
实际运行结果:121212
期待结果:121234
- 拷贝目标和源有重叠部分!
- 我们将前两个元素拷贝后3,4就变成了1,2,这样3,4就丢失了,在拷贝三和四的位置时实际拷贝的又是1,2。
- 我们想到一个解决方法就是倒着拷贝,这样就不会丢失3,4。但是倒着拷贝如果想实现题目中的第二种境况时又会发生丢失。
- 也就是说,既有需要从前向后拷贝的情况也有从后向前拷贝的情况。
模拟代码如下:
void * my_memmove ( void * dst, const void * src, size_t count)
{
void* ret=dst;
//不存在覆盖的情况下,直接进行拷贝
if(dst<=src||((char*)dst>=(char*)src+count))
{
while(count--)
{
*(char*) dst=*(char*) src;
dst=(char*) dst+1;
src=(char*) src+1;
}
}
//存在覆盖,逆向拷贝。
else
{
dst=(char*) dst+count-1;
src=(char*) src+count-1;
while(count--)
{
*(char*) dst= *(char*) src;
dst=(char*) dst-1;
src=(char*) src-1;
}
}
return ret;
}