void *mymemcpy(void *dest, const void *src, unsigned int count)
{
assert(dest);
assert(src);
if ( ((char*)dest - (char*)src < count ) && (dest >= src) )
{
char *tempDest = (char*)dest + count - 1;
const char* tempSrc = (const char*)src + count - 1;
while (count-- > 0)
{
*tempDest = *tempSrc;
tempDest--;
tempSrc--;
}
}
else
{
char *tempDest = (char*)dest;
const char* tempSrc = (const char*)src;
while (count-- > 0)
{
*tempDest = *tempSrc;
tempDest++;
tempSrc++;
}
}
return dest;
}
今天看到一道题目让实现memcpy函数。我用手写试了一下,然后再用机器调试,果然自己功夫不扎实,出了问题,考虑的也不全面。在看了别人的文章之后,重新写了一遍,并记录下来,以免自己以后忘记了。
if ( ((char*)dest - (char*)src < count ) && (dest>=src) )
这句判断dest和src占用空间是否有重叠。如下图所示,绿色区域为src占用空间。当dest位于绿色区域时,需要从src的末端开始复制,否则会导致src的内容被覆盖。dest位于其他位置时,从src的起始端开始复制。内存重叠的情况容易被忽略。

上面的代码虽然实现了功能,但是在有的编译器下会报很多warning,修改之后如下:
void *mymemcpy(void *dest, const void *src, size_t count)
{
if (dest == nullptr || src == nullptr)
{
return nullptr;
}
auto tempDistance = static_cast<char*>(dest) - static_cast<const char*>(src);
if ( tempDistance > 0 && static_cast<size_t>(tempDistance) < count )
{
char *tempDest = static_cast<char*>(dest) + count - 1;
const char* tempSrc = static_cast<const char*>(src) + count - 1;
while (count-- > 0)
{
*tempDest = *tempSrc;
tempDest--;
tempSrc--;
}
}
else
{
char *tempDest = static_cast<char*>(dest);
const char* tempSrc = static_cast<const char*>(src);
while (count-- > 0)
{
*tempDest = *tempSrc;
tempDest++;
tempSrc++;
}
}
return dest;
}
调用如下:
int ma=10;
int mb;
mymemcpy(&mb, &ma, sizeof(ma));
cout<<mb<<endl;
const char *maa = static_cast<const char*>("hello world");
char mbb[16];
mymemcpy(mbb, maa, strlen(maa));
cout<<mbb<<endl;
参考文章:
https://blog.youkuaiyun.com/TommyZht/article/details/47271525
https://blog.youkuaiyun.com/sszgg2006/article/details/7989404
本文深入探讨了手写memcpy函数的实现细节,包括如何处理源和目标内存区域可能的重叠情况,通过具体代码示例解释了不同情况下数据复制的方向选择,确保数据完整性和效率。同时,文章对比了不同实现方式在编译器警告方面的表现,提供了优化后的代码版本。
4056

被折叠的 条评论
为什么被折叠?



