错误方案
dst被移动了,返回的是移动后的dst,而且void指针不存在自增操作,所以显然是错误的
void *memcpy1(void *dst, const void *src, unsigned int len)
{
if(NULL == dst || NULL == src)
return NULL;
while(len--)
*dst++ = *src++; //void指针没有++操作
return dst;
}
不完美的方案
将指针转换成char类型的,那么在复制数据的时候就是一个字节一个字节的进行
void *memcpy2(void *dst, const void *src, unsigned int len)
{
if(NULL == dst || NULL == src)
return NULL;
char *p1 = (char *)dst;
char *p2 = (char *)src;
while(len--)
*p1++ = *p2++;
return dst;
}
效率优化的方案
整块的数据使用CPU位宽进行拷贝,剩余部分使用字符串进行拷贝
void *memcpy3(void *dst, const void *src, size_t len)
{
int blocks = len / sizeof(dst); /*按CPU位宽拷贝*/
int slice = len % sizeof(dst); /*剩余的按字节拷贝*/
unsigned long *p2 = (unsigned long *)src;
unsigned long *p1 = (unsigned long *)dst;
while(blocks--)
*p1++ = *p2++;
while(slice--)
*((char *)p1++) =*((char *)p2++);
return (void *)dst;
}
完善的方案
考虑到地址空间重叠的问题
1. 两者的地址空间不重叠[dst > src + len 或者 src > dst + len],从前往后复制
2. 两者的地址空间重叠,dst < src,从前往后复制
3. 两者的地址空间重叠,dst > src, 从后往前复制
void *memcpy4(void *dst, const void *src, size_t len)
{
//参数检查
if(NULL == dst || NULL == src)
return NULL;
if(dst > src + len || src > dst + len || dst < src)
{
char *p1 = (char *)dst;
char *p2 = (char *)src;
while(len--)
*p1++ = *p2++; //从前往后
}
else if(dst > src)
{
char *p1 = (char *)(dst + len - 1);
char *p2 = (char *)(src + len - 1);
while(len--)
*p1-- = *p2--; //从后往前
}
else if(dst == src)
{
//什么都不用做
}
return (void *)dst;
}
测试
int main()
{
char *src = "I am you father!";
char *dst;
int len = strlen(src);
cout << len << endl;
dst = (char *)mcpy4((void *)dst, (void *)src, strlen(src));
int len2 = strlen(dst);
cout << len2 << endl;
char *p = dst;
while(len2--)
{
//cout << *p++ << endl;
}
return 0;
}