柚子快報激活碼778899分享:開發(fā)語言 C語言內(nèi)存函數(shù)
柚子快報激活碼778899分享:開發(fā)語言 C語言內(nèi)存函數(shù)
1.memcpy使用和模擬實現(xiàn)
在前面我們學了字符串的拷貝函數(shù)strcpy但是我們不能只是拷貝字符串我們?nèi)绻胍截惼渌脑趺崔k呢?下面就來教學一個函數(shù)memcpy這個函數(shù)是針對內(nèi)存塊進行拷貝。
? memcpy ? 函數(shù)是一個標準的 C 語言庫函數(shù),用于從源地址復制一定數(shù)量的字節(jié)到目標地址。這個函數(shù)通常用于內(nèi)存操作,比如復制數(shù)組、結(jié)構(gòu)體或其他數(shù)據(jù)塊。
函數(shù)的原型是:
void * memcpy ( void * destination, const void * source, size_t num );
??destination?:指向目標內(nèi)存區(qū)域的指針,復制的數(shù)據(jù)將被寫入這里。 ??source? :指向源內(nèi)存區(qū)域的指針,數(shù)據(jù)將從這里復制。 ??num? :要復制的字節(jié)數(shù)。 ? ??memcpy?? 函數(shù)返回一個指向目標內(nèi)存區(qū)域的指針,即 ???destination??。
在使用這個函數(shù)的時候有注意事項:
下面還是老樣子,如果不能理解也沒有關系我會給一串代碼,在里面進行解釋:
#include
#include
int main()
{
int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
int arr2[10] = { 0 };
memcpy(arr2, arr1, 20);
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%d ", arr2[i]);
}
return 0;
}
下面在進行這個函數(shù)的模擬實現(xiàn):?
#define _CRT_SECURE_NO_WARNINGS
#include
#include
#include
//memcpy函數(shù)拷貝結(jié)束后,會返回目標空間的起始地址
void* my_memcpy(void* dst, const void* src, size_t num)
//實參都是int*但是這里的形參為什么是void*類型的指針?因為我們不只是想要傳整型類型的,恰好void*類型的可以接受更多
{
void* ret = dst;//這里為什么要把dst的地址存起來?因為dst在下面要進行解引用然后不斷地+1早已經(jīng)改變原先的地址了,返回就不準確
assert(dst);
assert(src);
while (num--)//我們傳入了20個字節(jié),要一個字節(jié)一個字節(jié)的進行打印,所以我們要進行20次循環(huán),
{
*(char*)dst = *(char*)src;//這里為什么要進行強制類型轉(zhuǎn)換成char*類型的,在進行解引用呢?
//因為void*類型不能解引用而且只有char*類型可以一次訪問一個字節(jié)
dst = (char*)dst + 1;
src = (char*)src + 1;
}
return(ret);//memcpy函數(shù)拷貝結(jié)束后,會返回目標空間的起始地址
}
int main()
{
int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
int arr2[10] = { 0 };
my_memcpy(arr2, arr1, 20);//這里給的是20個字節(jié)一個整型占4個字節(jié)所以只能復制5個數(shù)字
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%d ", arr2[i]);
}
return 0;
}
這就是函數(shù)的模擬實現(xiàn),我已經(jīng)在里面進行詳細的講解。?
但是下面的這句話是什么意思?
下面我再給串代碼講解一下:?這就是重合的情況。
int main()
{
int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };//如果我們想把12345拷貝放到34567中怎么進行?
//就是這樣arr1+2但是這樣我們認為打印出來是這樣的,下面這樣。
// 1 2 1 2 3 4 5 8 9 10
//但是結(jié)果可不是這樣的。
my_memcpy(arr1+2, arr1, 20);
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%d ", arr1[i]);
}
return 0;
}
我們可以看出來我們想的和打印出來的就是不同,但是為什么呢?聽我講解:?
int main()
{
int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
//當你打算把12345放大34567中的時候你先把1 2放到了3 4所在的地方,接下來會把3 4放到5 6上,但是這時3 4已經(jīng)是1 2了,所以最終還是把1 2放到5 6中,7也是這個道理。
my_memcpy(arr1+2, arr1, 20);
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%d ", arr1[i]);
}
return 0;
}
但是這里還是有個小細節(jié)的?,因為這是我們定義的my_memcpy函數(shù)如果使用memcpy函數(shù)是不是就不會有這種情況了?對的:
但是這串代碼是對的,還是不能說明我們memcpy這個函數(shù)就是可以拷貝重疊情況,C語言標準庫是規(guī)定不可以到但是這個函數(shù)還是做到了。并不沖突。
memcpy函數(shù)只用拷貝不重疊的情況,那重疊的情況怎么辦?這就要用到memmove函數(shù)了。
2.memmove函數(shù)的使用和模擬實現(xiàn)
還是老樣子我們來介紹一下什么是memmove函數(shù)
? memmove ? 函數(shù)是 C 語言標準庫中的一個函數(shù),用于在內(nèi)存中復制一塊數(shù)據(jù)。它與 ? memcpy ? 函數(shù)類似,但 ? memmove ? 能夠處理源和目標內(nèi)存區(qū)域重疊的情況。當源和目標內(nèi)存區(qū)域重疊時, memcpy ? 可能無法正確復制數(shù)據(jù),而 ? memmove ? 能夠確保數(shù)據(jù)的正確復制。
我們從這個定義中可以看出來這個函數(shù)的獨特的地方。,可以處理重疊的情況。
下面我們來說一下這個函數(shù)的原型:
void * memmove ( void * destination, const void * source, size_t num );
??dest??:指向目標內(nèi)存區(qū)域的指針。 ??src??:指向源內(nèi)存區(qū)域的指針。 ??n??:要復制的字節(jié)數(shù)。 ??memmove?? 函數(shù)返回一個指向目標內(nèi)存區(qū)域的指針。
原型其實是和memcopy函數(shù)大差不差的。那下面我們來看一下這個函數(shù)怎么處理重疊的情況
這里給出的還是上面的代碼:
#include
#include
int main()
{
int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
memmove(arr1+2, arr1, 20);
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%d ", arr1[i]);
}
return 0;
}
就是這樣,但是光看這個函數(shù)是不會了解本質(zhì)的,我們可以進行模擬實現(xiàn):
但是我們需要考慮一個問題我們怎么拷貝這個數(shù)字才能達到不會重疊拷貝的情況:
src 但是呢還是有一種情況我們還需要注意:如果我們想要把3 4 5 6?7拷貝到1 2 3 4 5這時候怎么辦呢? dest 重要:對于這兩種情況我們可以進行總結(jié):如果我想拷貝的一串數(shù)字在目標數(shù)字前(src 那接下來我們把函數(shù)模擬實現(xiàn)出來:那么這里我先給一個大體的框架: #define _CRT_SECURE_NO_WARNINGS #include #include void* my_memmove(void* dest, const void* src, size_t num) { if (dest < src) { //前—>后 } else { //后-->前 } return ret; } int main() { int arr1[] = { 1,2,3,4,5,6,7,8,9,10 }; my_memmove(arr1 + 2, arr1, 20); int i = 0; for (i = 0; i < 10; i++) { printf("%d ", arr1[i]); } return 0; } 就是這樣在接下來就開始進行細致的講解: #define _CRT_SECURE_NO_WARNINGS #include #include 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); //這里是什么意思?因為這是從后往前進行拷貝的,把dest和src強制類型轉(zhuǎn)換成char*類型之后是一個字節(jié) // 當我們再加上num,就是加上19個字節(jié)最后就成為了20個字節(jié),就是要拷貝的第五個數(shù)字的最后一個字節(jié) //那這里為什么是19因為num在進來的時候就 -- 了 } } return ret; } int main() { int arr1[] = { 1,2,3,4,5,6,7,8,9,10 }; my_memmove(arr1 + 2, arr1, 20); int i = 0; for (i = 0; i < 10; i++) { printf("%d ", arr1[i]); } return 0; } 總結(jié):這就是這兩個函數(shù)的區(qū)別我們可以了解一下。 柚子快報激活碼778899分享:開發(fā)語言 C語言內(nèi)存函數(shù) 好文鏈接
本文內(nèi)容根據(jù)網(wǎng)絡資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點和立場。
轉(zhuǎn)載請注明,如有侵權,聯(lián)系刪除。