其实之前我写过这篇……但是不够详细!今天重新写一下。
目录
memcpy
模拟实现memcpy
memmove
模拟实现memmove
memcpy
它的函数原型是:
void * memcpy ( void * destination, const void * source, size_t num );
查阅文档它的文档:
Copy block of memory
Copies the values of num bytes from the location pointed to by source directly to the memory block pointed to by destination.
The underlying type of the objects pointed to by both the source and destination pointers are irrelevant for this function; The result is a binary copy of the data.
The function does not check for any terminating null character in source - it always copies exactly num bytes.
To avoid overflows, the size of the arrays pointed to by both the destination and source parameters, shall be at least num bytes, and should not overlap (for overlapping memory blocks, memmove is a safer approach).
可以知道它的作用是从source的位置开始向后复制num个字节的数据到destination的内存位置。
它遇到'\0'的时候并不会停下来,不会对停止字符做检查。
如果source和destination有任何的重叠,复制的结果都是未定义的。
请看示例:
#include <stdio.h>
#include <string.h>
int main()
{
int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
int arr2[5] = { 0 };
int i = 0;
memcpy(arr2, arr1, 20);
for (i = 0;i < 5;i++)
{
printf("%d\n", arr2[i]);
}
return 0;
}
这是将arr1中的前五个元素给arr2。
为什么memcpy参数最后是20呢?
这是因为memcpy是内存拷贝,参数代表拷贝的字节数。
而int型是4个字节,要拷贝arr1中前五个元素给arr2,参数就为4*5=20。
运行结果如下:
模拟实现memcpy
#include <assert.h>
void* my_memcpy(void* dest, const void* src, size_t num)
{
void* ret = dest;
assert(dest && src);
//前->后
while (num--)
{
*(char*)dest = *(char*)src;
dest = (char*)dest + 1;
src = (char*)src + 1;
}
return ret;
}
但是……有虫豸(Bug)!
和这群虫豸在一起,怎能搞好政治呢?
一旦dest和src有重叠的部分,虫豸就产生了!
注意看,绿色方框是src,紫色方框是dest。
在拷贝时,会一个一个地将src的字符拷贝给dest。
如果是从前往后拷贝:
1到了原来3的位置,2到了原来4的位置,在这时3和4都已经没有了,那么5就成了1,6就成了2,7就成了1。
所以当函数调用完,dest里不是12345而是12121。
还有一种情况是从后往前拷贝:
5到了原来7的位置,4到了原来6的位置,3到了原来5的位置,2到了原来4的位置,1到了原来3的位置。这就不会出错!
如果src在dest之前,那就要从后往前拷贝。
同理,如果src在dest之后,就要从前往后拷贝。
总结下,dest的位置在第一个区域就要从前往后拷贝,在第二个区域就要从后往前拷贝,在第三个区域的话,从前往后拷贝和从后往前拷贝皆可~
那么该怎么实现这些功能,进而杀死虫豸?当然要请昆虫学家金载圭了!
memmove
它的函数原型如下:
void * memmove ( void * destination, const void * source, size_t num );
请看文档:
Move block of memory
Copies the values of num bytes from the location pointed by source to the memory block pointed by destination. Copying takes place as if an intermediate buffer were used, allowing the destination and source to overlap.
The underlying type of the objects pointed by both the source and destination pointers are irrelevant for this function; The result is a binary copy of the data.
The function does not check for any terminating null character in source - it always copies exactly num bytes.
To avoid overflows, the size of the arrays pointed by both the destination and source parameters, shall be at least num bytes.
和memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的。
如果源空间和目标空间出现重叠,就得使用memmove函数处理。
模拟实现memmove
void* my_memmove(void* dest, const void*src, size_t num)
{
void* ret = dest;
assert(dest && src);
if (dest < src)
{
//前-->后
while (num--)
{
*(char*)dest = *(char*)src;
dest = (char*)dest + 1;
src = (char*)src + 1;
}
}
else
{
//后->前
while (num--)
{
*((char*)dest+num) = *((char*)src + num);
}
}
return ret;
}