我们知道字符串操作函数的操作对象就是字符串,但想要将一段内存的数据复制到另一段内存中去的时候我们就得用到另外一种拷贝函数----内存拷贝函数。
内存拷贝函数的作用就是:将源内存地址的N个字节拷贝到目标内存地址中去。
一、memcpy函数的实现
memcpy的函数原型:void* memcpy(void* dst, const void* src, size_t count)
返回值说明:返回的是指向dst的void*指针
memcpy的作用就是将一块内存中的数据拷贝到另一块内存中去
下面将给出memcpy函数的代码实现:
void* my_memcpy(void *dst, const void *src, size_t size)
{
assert(dst);
assert(src);
char *str1 = (char *)dst;
const char *str2 = (const char *)src;
while (size)
{
*str1 = *str2;
str1++;
str2++;
size--;
}
return dst;
}
看到这里有人或许会问为什么要用void*呢?
因为写成是void*是为了能够接收各种类型指针,我们不知道具体要拷贝的内存里存放的是什么类型,所以写成是void*这样就不用去根据内存区域的参数类型而频繁的改动函数类型。
二、memmove函数的实现memmove函数的原型是:void* memmove(void* dst, const void* src, size_t count)
返回值说明:返回的是指向dst的void*的指针
memmove函数的作用与memcpy函数的作用相似都是内存拷贝函数,但是当两块内存重叠的时候,memcpy就不能保证拷贝的正确性,这个时候就要用到memmove函数。
下面我们来看一看memmove函数的代码实现:
void* my_memmove(void *dst, const void *src, size_t size)
{
assert(dst);
assert(src);
char *str1 = (char *)dst;
const char *str2 = (const char *)src;
if ((str2 > str1) && (str2< str1 + size))
{
while (size)
{
*str1 = *str2;
str1++;
str2++;
size--;
}
}
else
{
while (size--)
{
*(str1 + size) = *(str2 + size);
}
}
return dst;
}
三、对于memcpy函数和memmove函数的具体分析
在第一种的情况下,拷贝重叠的区域不会出现问题,拷贝内容是正确的;
在第二种的情况下,问题出现在右边的两个字节,这两个字节原来的内容就会首先被覆盖,而且没有被保存。接下来拷贝的时候拷贝的就是没有被保存的内容,所以就会出现问题的。
所以memmove针对memcpy出现错误的情况,就有了以下的调整:
1、当源内存的首地址等于目标内存的首地址,不进行任何拷贝;
2、当源内存的首地址大于目标内存的首地址,实行正向拷贝;
3、当源内存的首地址小于目标内存的首地址,实行反向拷贝。
总结:
1、memcpy实现从源(source)到目标(destin)的拷贝,src的源数据应该保留。
2、memmove实现移动一块字节,src的源数据可以不保留。
3、memcpy没有考虑内存覆盖的问题,memmove考虑了内存覆盖的问题并且给出了解决方案。
4、memcpy与memmove中不需要考虑数组越界的问题,dst长度大于src应该是调用者考虑的问题。