memcpy和memmove的區別以及內存重疊問題
轉自:https://www.codecomeon.com/posts/89/
區別
memcpy()
和 memmove()
都是C語言中的庫函數,在頭文件 string.h
中,作用是拷貝一定長度的內存的內容,原型分別如下:
void *memcpy(void *dst, const void *src, size_t count);
void *memmove(void *dst, const void *src, size_t count);
他們的作用是一樣的,唯一的區別是,當內存發生局部重疊的時候,memmove
保證拷貝的結果是正確的,memcpy
不保證拷貝的結果的正確。
函數原型
memcpy
-
原型:
void *memcpy(void *dest, const void *src, size_t n);
-
描述:
memcpy()
函數從 src 內存中拷貝 n 個字節到 dest 內存區域,但是源和目的的內存區域不能重疊。 -
返回值:memcpy()函數返回指向dest的指針。
memmove
-
原型:
void *memmove(void *dest, const void *src, size_t n);
-
描述:
memmove()
函數從 src 內存中拷貝 n 個字節到 dest 內存區域,但是源和目的的內存可以重疊。 -
返回值:memmove()函數返回一個指向dest的指針。
內存覆蓋情形
內存覆蓋的情形有以下兩種
memcpy面對內存覆蓋的兩種情形
memcpy 函數實現
void* my_memcpy(void* dst, const void* src, size_t n)
{char *tmp = (char*)dst;char *s_src = (char*)src;while(n--) {*tmp++ = *s_src++;}return dst;
}
從實現中可以看出memcpy()是從內存左側一個字節一個字節地將src中的內容拷貝到dest的內存中,這種實現方式導致了對于圖中第二種內存重疊情形下,最后兩個字節的拷貝值明顯不是原先的值了,新的值是變成了src的最開始的2個字節了。
而對于第一種內存覆蓋情況,memcpy的這種拷貝方式是可以的。
memcpy針對第二種情形的改進——memmove
而memmove就是針對第二種內存覆蓋情形,對memcpy進行了改進,改進代碼如下:
void* my_memmove(void* dst, const void* src, size_t n)
{char* s_dst;char* s_src;s_dst = (char*)dst;s_src = (char*)src;if(s_dst>s_src && (s_src+n>s_dst)) { //-------------------------第二種內存覆蓋的情形。s_dst = s_dst+n-1;s_src = s_src+n-1;while(n--) {*s_dst-- = *s_src--;}}else {while(n--) {*s_dst++ = *s_src++;}}return dst;
}
在第二種內存覆蓋的情形下面,memcpy會出錯,但是memmove是能正常工作的。