memcpy函数
原型函数1:
void *memcpy(void *dst, const void *src, size_t len)
{
if(NULL == dst || NULL == src){
return NULL;
}
void *ret = dst;
if(dst <= src || (char *)dst >= (char *)src + len){
//没有内存重叠,从低地址开始复制
while(len--){
*(char *)dst = *(char *)src;
dst = (char *)dst + 1;
src = (char *)src + 1;
}
}else{
//有内存重叠,从高地址开始复制
src = (char *)src + len - 1;
dst = (char *)dst + len - 1;
while(len--){
*(char *)dst = *(char *)src;
dst = (char *)dst - 1;
src = (char *)src - 1;
}
}
return ret;
}
原型函数2:
void* memcpy(void* dest, void* source, size_t count)
{
void* ret = dest;
//copy from lower address to higher address
while (count--)
*dest++ = *source;
return ret;
}
原型函数3:
void *memcpy(void *des,const void *src,size_t len)
{
char * result =des;
const char * from = src;
assert(des&&src);
while(len--)
{
*(result++) = *(from++);
}
return des;
}
1、调用memcpy函数前未初始化缓冲区
当调用memcpy函数时,如果第三个参数设置的复制字节数小于buffer的字节数,buffer尾部剩余字节中的内容是不可预知的,从而可能导致严重错误。所以,最好在使用memcpy函数前调用memset函数,将buffer中所有位置初始化为0。
memcpy函数是纯字节复制,不管字节中的内容,并且源地址和目标地址都需要确保有大于第三个参数指定的大小,否则复制会产生溢出,此外,源地址和目标地址所指向的存储空间也不能重叠。
2、这个函数不会检查参数dest与参数src所指向的数组(或其他类型)是否具有同样的空间。所以如果复制的字节数n超出了dest的空间容量,或者n超出src的容量,这个函数是不会进行判断的,这样就会很危险。这样,就需要程序员自己检查是否有溢出的情况出现。
同时要注意第三个参数长度,大多利用sizeof(src)计算其值,单要留心数值类型,总之是以字节为单位复制的。
3、(1)可以拷贝任何类型的对象,因为函数的参数类型是void*(未定义类型指针),也就是说传进去的实参可以是int*,short*,char*等等,
但是由于函数拷贝的过程是一个字节一个字节的拷贝的,所以实际操作的时候要把void*强制转化为char*,这样在指针加的时候才会保证每次加一个字节,
4、strcpy与memcpy的区别:
1、复制的内容不同。strcpy只能复制字符串,而memcpy可以复制任意内容,例如字符数组、整型、结构体、类等。
2、复制的方法不同。strcpy不需要指定长度,它遇到被复制字符的串结束符"\0"才结束,所以容易溢出。memcpy则是根据其第3个参数决定复制的长度。
3、用途不同。通常在复制字符串时用strcpy,而需要复制其他类型数据时则一般用memcpy
memcpy 在结构体中的妙用:
struct {
char name[40];
int age;
} person, person_copy;
int _tmain(int argc, _TCHAR* argv[])
{
char myname[] = "Pierre de Fermat";
/* using memcpy to copy string: */
memcpy(person.name, myname, strlen(myname) + 1);
person.age = 46;
/* using memcpy to copy structure: */
memcpy(&person_copy, &person, sizeof(person));
printf("person_copy: %s, %d \n", person_copy.name, person_copy.age);
getchar();
return 0;
}