首先我们来看memcpy原型函数的实现 (瑕疵版)
void *memcpy(void *dest, const void *src, size_t size)
{
assert((dest != NULL) && (src != NULL));
char *tmp = (char*)dest;
char *s_src = (char*)src;
while(size--) {
*tmp++ = *s_src++;
}
return dest;
}
一、src 指向数据不得长于 dest 指向的空间,不然会覆盖其他数据;
二、size不得大于 src 直线的数据块长度,不然会数组越界;
三、注意最后一个size指的是字节数
看以下这段代码
int a[10] = {0,1,2,3,4,5,6,7,8,9};
memcpy(a,a+3,2);
结果:3 1 2 3 4 5 6 7 8 9
问题:为什么只拷贝了一个数据呢?
原因是最后一个2代表的是字节数,而int是4个字节,所以在拷贝的时候只拷贝了一个数据。
修改后的代码
int a[10] = {0,1,2,3,4,5,6,7,8,9};
memcpy(a, a+3, 2*sizeof(int));
结果:3,4,2,3,4,5,6,7,8,9
三、内存重叠问题
看下面的代码
int a[10] = {0,1,2,3,4,5,6,7,8,9};
memcpy(a+3, a, 5*sizeof(int));
结果:0 1 2 0 1 2 0 1 8 9
下面我们来对结果进行分析:
拷贝五个字节:首先拷贝前三个数据到a+3这个地址
a变为:0 1 2 0 1 2 6 7 8 9
然后再拷贝两个数据内容,此时a+3和a+4地址内容的值已经变为0和1,所以最后的结果
a变为:0 1 2 0 1 2 0 1 8 9
最后改写memcpy的代码:
void *memcpy(void *dest, const void *src, size_t len)
{
//判断是否为空
if(NULL == dest || NULL == src)
{
return NULL;
}
void *ret = dest;
//判断内存是否重叠
if(dest <= src || (char *)dest >= (char *)src + len)
{
while(len--)
{
*(char*)dest = *(char*)src;
dest = (char *)dest + 1;
src = (char *)src +1;
}
}
return ret;
}