C語(yǔ)言進(jìn)階之內(nèi)存操作函數(shù)詳解
內(nèi)存操作函數(shù)
memcpy
頭文件:string.h
基本用途:進(jìn)行不相關(guān)(不重疊的內(nèi)存)拷貝。
函數(shù)原型:
void* memcpy(void* destination,//指向目標(biāo)數(shù)據(jù)的指針 const void* source,//指向被拷貝數(shù)據(jù)的指針 size_t num);//拷貝的數(shù)量(單位:字節(jié))
注:
1.基本原理:從source的位置開(kāi)始向后復(fù)制num個(gè)字節(jié)的數(shù)據(jù)到destnation的內(nèi)存位置。
2.這個(gè)函數(shù)與strcpy不同,它遇見(jiàn)'\0'的時(shí)候并不會(huì)停下來(lái)。
3.如果source和destnation有任何的重疊,復(fù)制的結(jié)果都是未定義的。
4.void* 之前講過(guò),為了保證泛用性,使用void*接收任意類型的數(shù)據(jù)。
使用舉例:
#include <stdio.h> #include <string.h> struct { char name[40]; int age; }person, person_copy; int main() { char myname[] = "Pierre de Fermat"; memcpy(person.name, myname, strlen(myname) + 1); person.age = 46; memcpy(&person_copy, &person, sizeof(person)); printf("person_copy: %s , %d\n", person_copy.name, person_copy.age); return 0; }
這是將字符串和結(jié)構(gòu)體成員變量拷貝到另一個(gè)結(jié)構(gòu)體的舉例。
為了更好的理解這一函數(shù),下面我們來(lái)模擬實(shí)現(xiàn)一下它。
void* my_memcpy(void* dest, const void* src, size_t num) { //斷言,防止dest或者src是空指針,如果是空指針則會(huì)報(bào)錯(cuò) assert(dest && src); //保存起始地址 void* ret = dest; while (num--) { //一次用最小單位(字節(jié))移動(dòng),保證泛用性 *(char*)dest = *(char*)src; //注:強(qiáng)制類型轉(zhuǎn)換只是臨時(shí)的,后面+1操作時(shí)已不存在 dest = (char*)dest + 1; src = (char*)src + 1; } //返回目標(biāo)空間的起始地址 return ret; }
memmove
頭文件:string.h
基本用途:重疊內(nèi)存塊的拷貝。
函數(shù)原型:
void* memove(void* destnation, const void* source, size_t num)
注:
1.和memcpy的區(qū)別就是memove函數(shù)處理的源內(nèi)存塊和目標(biāo)內(nèi)存塊可以重疊。
2.如果原空間和目標(biāo)空間出現(xiàn)重疊,就得使用memmove函數(shù)處理。
使用舉例:
#include <stdio.h> #include <string.h> int main() { char str[] = "memmove can be very useful....................."; //將字符串中從第15個(gè)元素的位置向后數(shù)共11個(gè)字符挪到從第20個(gè)字符開(kāi)始向后數(shù)第11個(gè)元素 memmove(str + 20, str + 15, 11); puts(str); return 0; }
該函數(shù)的模擬實(shí)現(xiàn):
#include <stdio.h> #include <string.h> #include <assert.h> void* my_memmove(void* dest, const void* src, size_t num) { assert(dest && src); //當(dāng)目標(biāo)位置地址小于源內(nèi)存塊數(shù)據(jù)地址時(shí),采用從前向后拷貝的方式 if (dest < src) { //根據(jù)字節(jié)數(shù)量一個(gè)一個(gè)移動(dòng)內(nèi)存單元 while (num--) { *(char*)dest = *(char*)src; //向后移動(dòng)一位 dest = (char*)dest + 1; src = (char*)dest + 1; } } //當(dāng)目標(biāo)為指針大于源內(nèi)存塊數(shù)據(jù)地址時(shí),采用從后向前的拷貝方式 else if (dest > src) { //將dest和src指針定位到各自最后的內(nèi)存地址處 dest = (char*)dest + num - 1; src = (char*)src + num - 1; //根據(jù)字節(jié)數(shù)量一個(gè)一個(gè)移動(dòng)內(nèi)存單元 while (num--) { *(char*)dest = *(char*)src; //向前移動(dòng)一位 dest = (char*)dest - 1; src = (char*)src - 1; } } }
memcmp
頭文件:stdio.h
基本用途:顧名思義,與strcmp函數(shù)類似,這個(gè)函數(shù)是比較內(nèi)存數(shù)據(jù)大小的(逐字節(jié))。
函數(shù)原型:
int memcmp(const void* ptr1, const void* ptr2, size_t num);
注:
1.比較從ptr1和ptr2開(kāi)始的num個(gè)字節(jié)
2.與strcmp返回值類似,仍是第一個(gè)指針內(nèi)容大于第二個(gè)指針的內(nèi)容,返回大于零的數(shù)字,第一個(gè)指針內(nèi)容小于第二個(gè)指針的內(nèi)容,返回小于零的數(shù)字,相等,返回零。
基本舉例:
#include <stdio.h> #include <string.h> int main() { char buffer1[] = "axxxxxxxxxxx"; char buffer2[] = "bbbbbbbbbbbb"; int n; n = memcmp(buffer1, buffer2, sizeof(buffer1)); printf("%d", n); return 0; }
結(jié)果:
到此這篇關(guān)于C語(yǔ)言進(jìn)階之內(nèi)存操作函數(shù)詳解的文章就介紹到這了,更多相關(guān)C語(yǔ)言內(nèi)存操作函數(shù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Linux/Manjaro如何配置Vscode的C/C++編譯環(huán)境
這篇文章主要介紹了Linux/Manjaro配置Vscode的C/C++編譯環(huán)境,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-05-05C++保存HBITMAP為位圖文件的實(shí)現(xiàn)方法
這篇文章主要介紹了C++保存HBITMAP為位圖文件的實(shí)現(xiàn)方法,幫助大家更好的理解和使用c++,感興趣的朋友可以了解下2021-01-01C語(yǔ)言中動(dòng)態(tài)內(nèi)存管理初學(xué)者容易犯的6個(gè)錯(cuò)誤分享
本篇文章主要介紹了初學(xué)者使用C語(yǔ)言中動(dòng)態(tài)內(nèi)存管理的4個(gè)函數(shù)時(shí)最容易犯的6個(gè)錯(cuò)誤,以及如何避免這些錯(cuò)誤,文中的示例代碼講解詳細(xì),感興趣的可以了解一下2023-04-04