我们首先来看一下官方的memcpy实现:
void* memcpy( void* dest, const void* src, std::size_t count );
1.从源地址拷贝count大小到目的地址中:
当目的地址的首地址在圈1或者圈2位置的时候,可以直接按字节进行拷贝
代码实现:
char* tempdest=(char*)dest;
const char* tempsrc=(const char*)src;
while (num--) {
*tempdest=*tempsrc;
tempsrc=tempsrc+1;
tempdest=tempdest+1;
}
2.自己实现内存拷贝的功能,很容易忽略到内存重叠的情况,这也是为什么莫名其妙会发生报错的原因.内存重叠的情况如图所示:
当目的地址的首地址出现在src到src+num的这个范围内的时候,就不能在使用以上的方法进行拷贝了,因为如果这样按字节进行拷贝,当4号位置拷贝到dest的首地址之后,就覆盖了src原有地址的值了,这样才会导致运行出错.
小编在实现功能之前,一直在想一个问题,就是在第一种情况的时候,如果dest出现在圈1的位置,那不也是会发生内存重叠吗?其实仔细研究一下,可以想到,就算按照字节一个一个拷贝,4->3,5->4,6->5,7->6,8->7,这样拷贝,即使原本内容发生改变了,但是我们需要的是拷贝完成的那个值,所以不用担心这种重叠.
第二种情况的代码实现:
char *tempdest=(char*)dest+num-1;
const char *tempsrc=(const char*)src+num-1;
while(num--){
*tempdest=*tempsrc;
tempsrc=tempsrc-1;
tempdest=tempdest-1;
}
整体memcpy的代码如下:
//实现memcpy的功能
#include <iostream>
using namespace std;
void *my_memcpy(void *dest,const void *src,size_t num){
if((dest==nullptr) || (src==nullptr)){
return nullptr;
}
//考虑到内存重叠的情况,若有重叠,需要从高地址向低地址拷贝,否则会出现把原有内容覆盖的情况
if(dest>(char*)src && dest<(char*)src+num){
char *tempdest=(char*)dest+num-1;
const char *tempsrc=(const char*)src+num-1;
while(num--){
*tempdest=*tempsrc;
tempsrc=tempsrc-1;
tempdest=tempdest-1;
}
}else{ // 如果没有发生内存重叠,则从低到高开始拷贝
char* tempdest=(char*)dest;
const char* tempsrc=(const char*)src;
while (num--) {
*tempdest=*tempsrc;
tempsrc=tempsrc+1;
tempdest=tempdest+1;
}
}
return dest;
}
int main()
{
char str[]="myfirst instance";
char str2[]="";
char *a=str;
char *b=str2;
my_memcpy(b,a,sizeof (str));
cout << b << endl;
cout << "-------------------------" << endl;
int p1=100;
int p2=200;
int *s1=&p1;
int *s2=&p2;
my_memcpy(s1,s2,sizeof (p2));
cout << *s1 << endl;
return 0;
}
感谢阅读,如果有什么错误的话,感谢各位大佬的指正!!!