memcpy
功能:内存拷贝函数,从数据源拷贝num个字节的数据到目标数组函数原型:
void * memcpy ( void * destination, const void * source, size_t num );
函数参数:
destination:指向目标数组的指针
source:指向数据源的指针
num:要拷贝的字节数
使用方法:
#include<stdio.h>
#include<string.h>
struct person
{
char* name;
char* sex;
};
int main()
{
//使用memcpy拷贝字符串
char* source = "there have something";
char desc[50];
std::memcpy(desc,source,strlen(source)+1); //不能用sizeof,sizeof(str2)指的是指针的大小
std::cout<<"dec[]="<<desc<<std::endl;
//拷贝字符串中的某些字符
char* s1 = "nothing is impossible";
char s2[40];
std::memcpy(s2,s1+10,strlen(s1)+1-10);
std::cout<<"s2: "<<s2<<std::endl;
//使用memcpy拷贝字符数组
char str1[] = "made in china";
char str2[50];
std::memcpy(str2,str1,sizeof(str1)); //或者strlen(str1)+1
std::cout<<"str2: "<<str2<<std::endl;
//使用memcpy拷贝结构体
person p;
person p2;
p.name = "Qiana";
p.sex = "女";
std::memcpy(&p2,&p,sizeof(person));
std::cout<<"p2.name: "<<p2.name<<std::endl;
std::cout<<"p2.sex: "<<p2.sex<<std::endl;
return 0;
}
注意:destination是指向目标数组的指针,数组名做参数,传的是数组首元素的首地址。当传的是一个指针的时候,就会出错,指针未初始化的时候,指向一个未知的区域,里面有随机值,且不知道大小和数据类型,当源数据对它进行赋值的时候,会出错所以memcpy的第一个参数,传一个大小大于源数据的数组。
char* s1 = "nothing is impossible";
char* s2;
std::memcpy(s2,s1+10,strlen(s1)+1-10);
//这样是不对的
模拟实现:
#include<stdio.h>
#include<string.h>
#include<assert.h>
void* mymemcpy(void* desc,const void* src,size_t size)
{
void* ret = desc;
char* str1 = (char*)desc;
char* str2 = (char*)src;
assert(str1);
assert(str2);
while(size--)
{
*str1++ = *str2++;
}
return ret;
}
int main()
{
char s1[] = "hello world";
char s2[20];
int a1[] = {1,2,3,4,5,6,7,8,9};
int a2[10];
mymemcpy(s2,s1,sizeof(s1));
std::cout<<s2<<std::endl;
mymemcpy(a2,a1,sizeof(a1));
int size = sizeof(a1)/sizeof(a1[0]);
for(int i = 0;i < size;++i)
{
std::cout<<a2[i]<<" ";
}
std::cout<<std::endl;
return 0;
}
memmove
功能:内存移动函数,从source所指向的对象复制num个到destination所指向的对象,允许内存重叠。
函数原型:
void * memmove ( void * destination, const void * source, size_t num );
内存重叠:例如,char s1[] = "123456789" ,复制“3456”到“5678”,“56”是重叠部分,若用memcpy拷贝,将“34”拷贝到了“56”的位置,导致将“56”拷贝到“78”时,“56”已经不存在了,被“34”覆盖了。而memmove就是解决memcpy不能内存重叠的问题,比memcpy更加的安全。如果目标区域和源区域没有重叠,则memmove和memcpy的函数作用相同。
函数参数:
destination:指向目标数组的指针
source:指向数据源的指针
num:要拷贝的字节数
使用方法:
#include<stdio.h>
#include<string.h>
int main()
{
char str1[32] = "juice in the July";
char str2[32] = "hello world";
//使用memmove拷贝到另一个数组中,同memcpy
memmove(str2,str1,sizeof(str1));
std::cout<<"str2:"<<str2<<std::endl;
memmove(str2,"begin\0end",sizeof(str2)); //\0是字符串的结束标志
std::cout<<"str2:"<<str2<<std::endl;
//在一个数组中进行拷贝
memmove(str1+13,str1+6,2);
puts(str1);
//进行内存重叠的拷贝
char str3[] = "123456789";
memmove(str3+4,str3+2,4);
std::cout<<"str3:"<<str3<<std::endl;
return 0;
}
模拟实现:
void* my_memmove(void* desc,const void* src,size_t num)
{
void* ret = desc;
char* str1 = (char*)desc;
char* str2 = (char*)src;
assert(str1);
assert(str2);
if(str1 > str2)
{
while(num--) //循环num次,由num=num-1到num=0
{
*(str1+num) = *(str2+num);
}
}
else
{
while(num--)
{
*str1++ = *str2++;
}
}
return ret;
}
int main()
{
char s1[] = "123456789";
char s2[] = "234567123456";
my_memmove(s1+4,s1+2,4);
std::cout<<"s1: "<<s1<<std::endl;
my_memmove(s1,s1+5,4);
std::cout<<"s1: "<<s1<<std::endl;
my_memmove(s2,s1,sizeof(s1));
std::cout<<"s2: "<<s2<<std::endl;
return 0;
}
memcpy与memmove的区别:
memcpy是内存拷贝函数,memmove是内存移动函数,两个函数的作用差不多,区别在于memmove允许内存重叠,也就是允许反向拷贝。memmove比memcpy更安全一些。
O(∩_∩)O!