文章目錄
- memcpy——記憶體拷貝1
- 1.函式功能
- 2.模擬實作
- memmove——記憶體拷貝2(可重疊)
- 1.函式功能
- 2.模擬實作
- memcmp——記憶體比較
- memset——記憶體設定
memcpy——記憶體拷貝1
1.函式功能

memcpy函式是用于拷貝記憶體塊的函式,該函式有三個引數,第一個引數為拷貝的目標地址(void * destination),第二個引數為拷貝源地址(const void * source),因為在拷貝程序中源字串不會變化,所以引數用 const 修飾,第三個引數為在記憶體中拷貝的位元組數(size_t num),該引數決定了拷貝記憶體的大小,回傳值為拷貝目標的的首地址,因為不清楚拷貝資料的型別,所以回傳型別為 void* 型,
對于該函式,要注意:
1.函式memcpy從 source 的位置開始向后復制 num 個位元組的資料到destination的記憶體位置,
2.這個函式在遇到 ‘\0’ 的時候并不會停下來,
3.如果source和destination有任何的重疊,復制的結果都是未定義的(為拷貝的內容會被覆寫),
舉個栗子:

2.模擬實作
#include<stdio.h>
#include<string.h>
#include<assert.h>
void* my_memcpy(void* dest, const void* src, size_t num)
{
assert(dest&&src);
void* ret = dest;
while (num--)
{
*(char*)dest = *(char*)src;
dest = (char*)dest + 1;
src = (char*)src + 1;
}
return ret;
}
int main()
{
int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
int arr2[10] = { 0 };
my_memcpy(arr2, arr1, 20);
return 0;
}
memmove——記憶體拷貝2(可重疊)
1.函式功能

該函式的引數的意義與回傳型別同memcpy一樣,但是該函式的功能與memcpy略有區別,區別在于:
memmove函式的源記憶體塊和目標記憶體塊是可以重疊的,而memcpy函式的源記憶體塊和目標記憶體塊是不可以重疊的,
所以在拷貝中如果源空間和目標空間出現重疊,就得使用memmove函式處理,
例如:

可以看出,在上述代碼中,第一次使用memmove函式時,arr1 < arr+3 ,且拷貝的記憶體的大小為20位元組(即5個整型),即將arr1中的"4 5 6 7 8"序列拷貝到" 1 2 3 4 5"的位置上,兩序列有重疊的部分,所以為了拷貝成功,函式是將序列"4 5 6 7 8" 中的記憶體(每個位元組)依次從前向后拷貝(若從后向前拷貝,則原本待拷貝的內容將會被首先拷貝的內容覆寫,從而造成拷貝的序列出錯),所以拷貝的程序如下圖所示:

而在第二次使用memmove函式時,arr2+2 > arr2,拷貝的記憶體大小為20位元組,為了保證拷貝程序中的合理,第二次拷貝時記憶體中的序列時從后向前拷貝,如下:

所以從以上兩次的拷貝結果可以看出memmove的拷貝機制為:

當 dest < src 時,src 指向的內容拷貝的方式為從前向后拷貝
當 dest > src 時,src 指向的內容拷貝的方式為從后向前拷貝(如上圖)
2.模擬實作
根據拷貝機制我們可以模擬實作該函式:
#include<stdio.h>
#include<string.h>
#include<assert.h>
void* my_memmove(void* dest, const void* src, size_t num)
{
assert(dest && src);//斷言
void* ret = dest;//保存待回傳的首地址
if (dest < src)
{
while (num--)
{
*(char*)dest = *(char*)src;//通過強制型別轉換來實作每個位元組的拷貝
dest = (char*)dest + 1;
src = (char*)src + 1;
}
}
else
{
while (num--)
{
*(((char*)dest) + num) = *(((char*)src) + num);
}
}
return ret;
}
int main()
{
int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
my_memmove(arr1+3, arr1, 20);
return 0;
}
memcmp——記憶體比較
函式功能:

該函式用來比較兩個記憶體塊大小的函式,函式有三個引數,ptr1,ptr2分別為兩個待比較的內容的首地址,因為不清楚待比較是內容是什么型別,所以兩指標的型別被定義為void* 型,第三個引數為待比較的記憶體大小(單位位元組);與strcmp函式的比較方式類似,但比較的內容不同,該函式會比較從ptr1和ptr2指標開始的num個位元組,當ptr1大于ptr2的時候回傳一個大于0的數;當prt1等于ptr2的時候回傳0;當ptr1小于ptr2的時候回傳一個小于0的數,
栗子如下:
#include<stdio.h>
#include<string.h>
int main()
{
int arr1[] = { 1, 2, 3, 4 };
int arr2[] = { 1, 2, 4, 5 };
int ret1 = memcmp(arr1, arr2, 8);
int ret2 = memcmp(arr1, arr2, 9);
printf("%d %d", ret1, ret2);
return 0;
}

因為arr1,與arr2 在記憶體中的存盤的記憶體如下圖,因為前8個位元組的內容相同,所以ret1=0,而第9個位元組中的內容不同,所以ret2=-1,

memset——記憶體設定
函式功能:

該函式是將記憶體塊中的某一部分設定為特定的字符;函式有三個引數,第一個引數是開始設定記憶體的起始位置,第二個引數是記憶體將要被設計成的特定字符,第三個引數是從起始位置開始需要設定的記憶體的位元組數,
需要注意的是,該函式設定記憶體時是一個位元組一個位元組地進行設定,
舉個例子:

再例如:
將字串 “Hello world!” ,變為 “##### world!” ,代碼如下:
#include<stdio.h>
#include<string.h>
int main()
{
char str[] = "Hello world!";
char* ret = memset(str, '#', 5);//字符‘#’傳入函式記憶體的為相應的ASCII值,
//設定的記憶體大小為5個位元組
printf("%s\n", ret);
return 0;
}

轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/296926.html
標籤:其他
