/*
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(dest); const char *pSrc=static_cast(src); if( pDest>pSrc && pDest { for(size_t i=count-1; i<=0; ++i) { pDest[i]=pSrc[i]; } } else { for(size_t i=0; 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; }
|