C語言中的內存函數有如下這些
- memcpy
- memmove
- memcmp
- memset
下面看看memcpy函數
memcpy
我們想想,之前有那個字符串拷貝的函數,即strcpy函數。都有拷貝的函數了,為什么還要這個內存拷貝函數呢?
不能直接用strcpy嗎?這是一個好問題,那下面就試試它。
我們准備兩個整型數組,分別為arr1和arr2,然后通過strcpy函數把arr1的內容拷貝到arr2中,代碼如下
int main()
{
int arr1[] = { 1,2,3,4,5 };
int arr2[5] = { 0 };
// 把arr1的內容拷貝到arr2中
strcpy(arr2, arr1);
return 0;
}
那么這里肯定會有警告,因為類型不同。
直接運行,通過Debug,看內存,可以發現實現不了完整的拷貝,strcpy只拷貝了一個字節
顯然,strcpy函數不適用於其他類型的數據拷貝,所以呢,就出現內存拷貝了,使任意類型的數據都能進行拷貝。
老規矩,我們還是看看文檔是怎樣說的,如下
void * memcpy ( void * destination, const void * source, size_t num );Copy block of memory
拷貝內存塊(拷貝內存數據)
Copies the values of num bytes from the location pointed to by source directly to the memory block pointed to by destination.
從source(源內存塊位置)直接指向的地方開始復制num個字節的數據到destination指向的內存塊位置。
The underlying type of the objects pointed to by both the source and destination pointers are irrelevant for this function; The result is a binary copy of the data.
這句話沒看懂,不影響我們學這個。
The function does not check for any terminating null character in source - it always copies exactly num bytes.
這個函數不會檢查'\0',不會遇到'\0'就停下來,它就只認識要復制的num個字節數據。
To avoid overflows, the size of the arrays pointed to by both the destination and source parameters, shall be at least num bytes, and should not overlap (for overlapping memory blocks, memmove is a safer approach).
為了避免溢出,這兩個數組的大小至少為num個字節,而且這兩個數組內存位置不應該重疊。
我們從文檔中可以看出
- 參數中除了要復制的
字節數num,其他的參數類型基本都是void*,返回值也是void* - 該函數是從
source的位置開始向后復制num個字節的數據到destination的內存位置。 - 該函數在遇到
'\0'的時候並不會停下來。 source和destination不能有有任何的重疊。
實現
void* 不能直接解引用,那么如何復制呢?答案是進行類型強轉,轉換成char*,一個一個字節地復制過去。
一開始得先搞一個指針變量*rest來存儲dest,不然目的地址后面發生改變就不知道地址是哪里了。接下來就是主要操作了,把src指向的數據復制給dest,即*(char*)dest = *(char*)src,然后這兩個指針都進行偏移,往后走,繼續復制,就是循環下去了,直到num個字節復制完就結束,返回目的地址rest。代碼如下
斷言指針不為空是個好習慣~
void* my_memcpy(void* dest, const void* src, size_t num)
{
assert(dest != NULL);
assert(src != NULL);
void* rest = dest;
// void* 不能直接解引用,那么如何復制呢?
// 給了num個字節,也就是需要復制num個字節
// 那就轉換成char*,一個一個字節的復制過去
while (num--)
{
*(char*)dest = *(char*)src;
//++(char*)dest;
//++(char*)src;
((char*)dest)++;
((char*)src)++;
}
return rest;
}
以上,就是memcpy函數的實現。
測試代碼
我們就使用下面的測試代碼,測試下自己實現的my_memcpy函數,通過Debug來觀察內存數據的變化。
struct S
{
char name[20];
int age;
};
int main()
{
int arr1[] = { 1,2,3,4,5 };
int arr2[5] = { 0 };
my_memcpy(arr2, arr1, sizeof(arr1));
struct S arr3[] = { {"LeBron", 36}, {"Kobe", 41} };
struct S arr4[3] = { 0 };
my_memcpy(arr4, arr3, sizeof(arr3));
return 0;
}
最后,謝謝你看到這里,謝謝你認真對待我的努力,希望這篇博客有幫到你
你輕輕一個贊,就是我世界里的一顆星
還有因本人水平有限,如有錯誤以及不足之處,歡迎靚仔靚女們指出。
