/*
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;
}
|