自己实现memcpy和memmove,两者的区别及内存重叠问题

memcpy和memmove最大的区别就是,memcpy会出现内存覆盖,而memmove不会

废话不多说直接上代码

#include<iostream>
#include<assert.h>
using namespace std;

void *my_memcpy(void* dest, const void* src, size_t count)//不考虑内存重叠,若考虑,则同下memmove
{
	assert(dest != NULL&&src != NULL);
	char* pdest =(char*) dest;
	const char* psrc =(const char*) src;
	while (count--)          
		*pdest++ = *psrc++;
	return dest;
}

void* my_memmove(void* dest, void* src, size_t count)//同考虑内存重叠的memcpy
{
	assert(dest != NULL && src != NULL);
	char* pdest = (char*)dest;
	const char* psrc = (char*)src;
	if(psrc >= pdest || pdest >= (psrc + count))//当源内存地址在目的内存地址之后或者目的地址在源内存地址+count之后,可以正常拷贝
	{
		while (count--)
		{
			*pdest++ = *psrc++;
		}
	}
	else     //否则需要从后往前拷贝,防止出现覆盖
	{
		while (count--)
		{
			*(pdest + count) = *(psrc + count);
		}
	}
	return dest;
} 

这是我自己实现这两个函数的代码。

主函数:

void main()
{
char a[]="abcdefg";
char *b=a+2;
cout<<b<<endl;
my_memcpy(b,a,5);
cout<<b<<endl;

}

在这里主函数本该输出的是cdefg和abcde,但是编译器输出如下:

再看调用库函数的memcpy:

void main()
{
char a[]="abcdefg";
char *b=a+2;
cout<<b<<endl;
my_memcpy(b,a,5);
cout<<b<<endl;

}

这里并不是我的my_memcpy写的有问题,而是编译器优化了系统的memcpy,这里只是为了区分memcpy和memmove,所以选择调用自己的my_memcpy,在此解释。



下面说一下为什么出现了内存重叠:

a  b  c  d  e  f  g     这是a字符串,即Src

        c  d  e  f  g     这是b字符串,即Dest

首先拷贝上面的a到下面c的位置,然后b到d的位置,但内存中c的位置已经变成了a,所以又拷贝a到e的位置,内存中的d变成了b,所以又拷贝b到f的位置,以此类推,输出结果为ababa,这就是所说的内存重叠

具体可参考:https://blog.csdn.net/li_ning_/article/details/51418400

在面试的时候,基本会让写考虑内存重叠的my_memcpy,其实就是上面的my_memove,实现方式是判断是否会出现内存重叠的情况,如果会出现那么就从后往前拷贝,防止这种情况的出现。


猜你喜欢

转载自blog.csdn.net/manonghouyiming/article/details/80055845
今日推荐