函數原型:
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
