函數原型:
void *memcpy( void *dest, const void *src, size_t count ); void *memmove( void* dest, const void* src, size_t count );
1.memcpy和memmove相同點
都是用於從src拷貝count個字節到dest。
2.memcpy和memmove區別
如果目標區域和源區域有重疊的話:
memcpy不能夠確保源串所在重疊區域在拷貝之前被覆蓋。
memmove能夠保證源串在被覆蓋之前將重疊區域的字節拷貝到目標區域中,復制后src內容會被更改,當目標區域與源區域沒有重疊則和memcpy函數功能相同。
但當源內存和目標內存存在重疊時,memcpy會出現錯誤,而memmove能正確地實施拷貝,但這也增加了一點點開銷。
memmove的處理措施:
(1)當源內存的首地址等於目標內存的首地址時,不進行任何拷貝
(2)當源內存的首地址大於目標內存的首地址時,實行正向拷貝
(3)當源內存的首地址小於目標內存的首地址時,實行反向拷貝
3.Linux下的實現過程
linux下,兩個函數都在頭文件string.h中定義,函數原型為:
void * __cdecl memcpy ( void * dst,const void * src,size_t count); void * __cdecl memmove ( void * dst,const void * src,size_t count); //實現代碼如下: void * __cdecl memcpy ( void * dst,const void * src,size_t count){ void * ret = dst; while (count--) { // 注意, memcpy函數沒有處理dst和src區域是否重疊的問題 *(char *)dst = *(char *)src; dst = (char *)dst + 1; src = (char *)src + 1; } return(ret); } void * __cdecl memmove ( void * dst,const void * src,size_t count){ void * ret = dst; if (dst <= src || (char *)dst >= ((char *)src + count)) { // 若dst和src區域沒有重疊,則從起始處開始逐一拷貝 while (count--){ *(char *)dst = *(char *)src; dst = (char *)dst + 1; src = (char *)src + 1; } } else{ // 若dst和src 區域交叉,則從尾部開始向起始位置拷貝,這樣可以避免數據沖突 dst = (char *)dst + count - 1; src = (char *)src + count - 1; while (count--){ *(char *)dst = *(char *)src; dst = (char *)dst - 1; src = (char *)src - 1; } } return(ret); }
當src和dst區域沒有重疊時,兩個函數是完全一樣的。否則,memcpy不能正常工作的,memmove是可以正常工作的。
4.Windows平台
#include <stdio.h> #include <string.h> /* VS2010, Windows XP, Debug模式下運行 */ int main(void) { void test_memfunc(void); test_memfunc(); return 0; } void test_memfunc(void){ char s1[] = "abcdefgefghijklmnopq";//首地址:0x0012ff48 char s2[] = "123456789";//首地址:0x0012ff34 char *c = NULL; int l = sizeof(s1);//數組s1長度為21 /* 內存重疊 : s2覆蓋了原s1()的一部分空間。 即: s2(0x0012ff34-0x0012ff49) 的內存地址范圍和s1(0x0012ff48-0x0012ff5c)的內存地址范圍發生重疊 */ c = memcpy(s2,s1,sizeof(s1));//改用memmove同樣運行出錯 /* 運行出錯:變量s1損壞。 Run-Time Check Failure #2 - Stack around the variable 's2' was corrupted. */ printf("%s",s1); }
windows平台下,當發生內存重疊的時候,都不能正常運行,運行棧被破壞,提示錯誤:Run-Time Check Failure #2 - Stack around the variable 's2' was corrupted.
參考:
http://msdn.microsoft.com/en-us/magazine/cc301374.aspx
http://www.cnblogs.com/BeyondAnyTime/archive/2012/05/10/2495013.html