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