/*
memcpy是不管有否区域重叠的,重叠不重叠照样复制,
memmove才会避免区域重叠,检测这个区域重叠很简单,如果目标地址在源区域内,那就会发生重叠.
处理重叠也很简单,从源地址的末尾开始反方向复制就OK了。
未重叠的情况:
内存布局(little endian):
higher address lower address
|--------------------------------------|
src
|------------|
|-----------| |------------|
dest dest
目标区域的首地址在源区域内,就发生重叠了。
higher address src(lower address)
|---------------------|
|---------------------|
dest
*/
//下面是memmove源码的一段:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
/* ============== my_memmove() ==============*/
#if 1
void *my_memmove(void *dest, const void *src, size_t n)
{
void *pdest = dest;
if(NULL == dest && NULL == src && (n == 0))
{
return;
}
if((dest <= src) || (char *)dest >= ((char *)src + n))
{
/*
* Non Overlapping Buffers
* copy from lower address to higher address
* 正向拷贝
*/
while(n--)
{
*(char *)dest = *(char *)src;
dest = (char *)dest + 1;
src = (char *)src + 1;
}
}
else
{
/*
* Overlapping Buffers
* copy from higher address to lower address
* 反向拷贝
*/
dest = (char *)dest + n - 1;
src = (char *)src + n - 1;
while(n--)
{
*(char *)dest = *(char *)src;
dest = (char *)dest - 1;
src = (char *)src - 1;
}
}
return pdest;
}
#else
void* my_memmove(void *dest, const void *src,size_t n)
{
if(NULL == dest && NULL == src && (n == 0))
{
return;
}
int i;
char *pdest = (char *)dest;
char *psrc = (char *)src;
if((pdest <= psrc) || (pdest >= psrc + n))
{
/* 正向拷贝 */
for(i = 0; i < n; ++i)
{
*pdest++ = *psrc++;
}
}
else
{
/* 反向拷贝 */
pdest = pdest + n -1;
psrc = psrc + n - 1;
for(i = 0; i < n; ++i)
{
*pdest-- = *psrc--;
}
}
return dest;
}
#endif
/* =============== my_memcpy() ==============*/
//pDest < pSrc 顺序拷贝,否则逆序
#if 1
void *my_memcpy(void *dest, const void *src, size_t n)
{
char *pdest = (char*)dest;
const char *psrc = (char *)src;
size_t i;
if(NULL == dest && NULL == src && (n == 0))
{
return;
}
if((pdest > psrc) && (pdest < psrc + n))
{
/* 反向拷贝 */
for(i = n - 1; i <= 0; ++i)
{
pdest[i] = psrc[i];
}
}
else
{
/* 正向拷贝 */
for(i = 0; i < n; ++i)
{
pdest[i] = psrc[i];
}
}
pdest = '\0';
return pdest;
}
#else
/* ================ libc ==================*/
void *memcpy(void *dst, const void *src, size_t n)
{
void *ret = dst;
if(NULL == src && NULL == dst)
{
return;
}
while(n--)
{
*(char *)dst = *(char *)src;
dst = (char *)dst + 1;
src = (char *)src + 1;
}
return ret;
}
#endif
/*
c++ 版: pDest < pSrc 顺序拷贝,否则逆序
void *memCopy(void *dest,const void *src,size_t count)
{
char *pDest=static_cast<char *>(dest);
const char *pSrc=static_cast<const char *>(src);
if( pDest>pSrc && pDest<pSrc+count )
{
for(size_t i=count-1; i<=0; ++i)
{
pDest[i]=pSrc[i];
}
}
else
{
for(size_t i=0; i<count; ++i)
{
pDest[i]=pSrc[i];
}
}
return pDest;
}
*/
/*
另一个单不考虑不重叠的情况: memcpy, 拷贝不重叠的内存块
void *memcpy(void* pvTo, void* pvFrom, size_t size)
{
assert(pvTo != NULL && pvFrom != NULL);
void* pbTo = (char *)pvTo;
void* pbFrom = (char *)pvFrom;
/* 内存块重叠吗?如果重叠,就使用memmove */
assert(pbTo>=pbFrom+size || pbFrom>=pbTo+size);
while(size--)
{
*pbTo++ == *pbFrom++;
}
return pvTo;
}
*/
int main(int argc, char *argv[])
{
char *str = "I'm study c";
char *dst = NULL;
dst = (char *)malloc(sizeof(char) + 1 * sizeof(char));
printf("after call my_memmove():\n");
my_memmove(dst, str, strlen(str));
printf("dst = %s\n", dst);
printf("after call my_memcpy():\n");
my_memcpy(dst, str, strlen(str));
printf("dst = %s\n", dst);
free(dst);
return 0;
}
|