C語(yǔ)言動(dòng)態(tài)分配內(nèi)存-文檔資料_第1頁(yè)
C語(yǔ)言動(dòng)態(tài)分配內(nèi)存-文檔資料_第2頁(yè)
C語(yǔ)言動(dòng)態(tài)分配內(nèi)存-文檔資料_第3頁(yè)
C語(yǔ)言動(dòng)態(tài)分配內(nèi)存-文檔資料_第4頁(yè)
C語(yǔ)言動(dòng)態(tài)分配內(nèi)存-文檔資料_第5頁(yè)
已閱讀5頁(yè),還剩57頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶(hù)提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、11動(dòng)態(tài)內(nèi)存分配基礎(chǔ)2動(dòng)態(tài)內(nèi)存分配實(shí)例3動(dòng)態(tài)內(nèi)存分配進(jìn)階C語(yǔ)言動(dòng)態(tài)分配內(nèi)存2動(dòng)態(tài)分配內(nèi)存基礎(chǔ)3動(dòng)態(tài)分配內(nèi)存概述什么時(shí)候需要?jiǎng)討B(tài)分配內(nèi)存?實(shí)例:順序?qū)σ慌募M(jìn)行解析,但是不知道文件的大小,如何建立緩沖區(qū)?4malloc函數(shù)malloc函數(shù)原型:void * malloc(size_t n);n是要分配的內(nèi)存的大小,返回值是分配內(nèi)存的塊的首地址 5malloc函數(shù)例1:使用malloc函數(shù)分配一個(gè)可以容納10個(gè)整型元素的內(nèi)存空間,并將其用作一個(gè)整型數(shù)組6malloc函數(shù)關(guān)鍵代碼:int * array;array = (int *)malloc(10 * sizeof(int);注意:內(nèi)存大小不

2、能寫(xiě)成數(shù)組元素的個(gè)數(shù)7malloc函數(shù) 例2:定義一個(gè)結(jié)構(gòu)struct testint a;char b;int c10;使用malloc函數(shù)分配一個(gè)此種結(jié)構(gòu)類(lèi)型的對(duì)象8malloc函數(shù) 關(guān)鍵代碼:struct test * p;p = (struct test *)malloc(sizeof(struct test);9需要注意的問(wèn)題(1)malloc函數(shù)是一個(gè)庫(kù)函數(shù),它并不是C語(yǔ)言中的關(guān)鍵字:需要頭文件才可以使用該函數(shù)并不是所有的平臺(tái)都可以使用該函數(shù),尤其是一些單片機(jī)系統(tǒng)10需要注意的問(wèn)題(2)指針類(lèi)型轉(zhuǎn)換是必須的,關(guān)系到接收分配好的內(nèi)存塊的地址可以向前看多少字節(jié)。如果不做指針類(lèi)型轉(zhuǎn)換會(huì)怎

3、么樣?void * 指針存在的意義。11需要注意的問(wèn)題(3)內(nèi)存塊大小的可移植性問(wèn)題分配一個(gè)整型變量數(shù)組應(yīng)使用:數(shù)組元素個(gè)數(shù) * sizeof(int)確定內(nèi)存塊的大小問(wèn)題:sizeof和strlen函數(shù)的區(qū)別12free函數(shù)free函數(shù)原型:void free(void * p);p是要釋放的已分配內(nèi)存的塊的首地址13free函數(shù)釋放一塊動(dòng)態(tài)分配的內(nèi)存:例如:int *p;p = (int *)malloc(sizeof(int);free(p);14需要注意的問(wèn)題(1)free函數(shù)同樣是一個(gè)庫(kù)函數(shù)(2)free函數(shù)的參數(shù)必須是一個(gè)由動(dòng)態(tài)內(nèi)存分配方法分配的內(nèi)存塊的首地址(使用malloc函數(shù)

4、分配的內(nèi)存)15動(dòng)態(tài)分配內(nèi)存特點(diǎn)內(nèi)存空間大小可以是一個(gè)變量,其值在運(yùn)行時(shí)確定內(nèi)存空間在運(yùn)行時(shí)分配,在程序結(jié)束時(shí)收回;內(nèi)存的分配由操作系統(tǒng)參與完成動(dòng)態(tài)分配的內(nèi)存空間在未釋放之前均可以被引用,保證其生命期16鏈表17鏈表的概述 struct node int node; /* 數(shù)據(jù)域,存儲(chǔ)結(jié)點(diǎn)的值 */struct node * next;18鏈表示意圖value1value 2value 3value 4NULL19處理鏈表使用的函數(shù)動(dòng)態(tài)申請(qǐng)內(nèi)存:void * malloc(size_t n);釋放動(dòng)態(tài)內(nèi)存:void free(void *); 20插入一個(gè)結(jié)點(diǎn) struct node *p =

5、 &b;a.next = p; /* 連接a結(jié)點(diǎn)和b結(jié)點(diǎn) */ b.next = &c; /* 連接b結(jié)點(diǎn)和c結(jié)點(diǎn) */21刪除一個(gè)結(jié)點(diǎn) struct node *p = &b;a.next = b.next; /* 連接a結(jié)點(diǎn)和c結(jié)點(diǎn) */ free(p); /* 摘下的b結(jié)點(diǎn)一定要釋放掉*/ 22動(dòng)態(tài)內(nèi)存分配實(shí)例23動(dòng)態(tài)內(nèi)存分配實(shí)例設(shè)計(jì)一個(gè)學(xué)生鏈表,其每個(gè)結(jié)點(diǎn)是一個(gè)學(xué)生信息的集合。每個(gè)結(jié)點(diǎn)包含如下信息:學(xué)生姓名、學(xué)號(hào)、C語(yǔ)言成績(jī)?nèi)?xiàng)。初始時(shí)擁有3個(gè)學(xué)生,添加一個(gè)學(xué)生(使用一個(gè)函數(shù)實(shí)現(xiàn)此操作),再刪除一個(gè)學(xué)生(使用另一個(gè)函數(shù)實(shí)現(xiàn)此操作),并打印該學(xué)生的信息。24實(shí)例關(guān)鍵點(diǎn)分析結(jié)點(diǎn)結(jié)構(gòu):str

6、uct infochar name10;int id;int score;struct stdstruct info;struct std * next;25實(shí)例關(guān)鍵點(diǎn)分析main函數(shù):int main(void)/* 初始化學(xué)生鏈表 */* 插入一個(gè)學(xué)生信息結(jié)點(diǎn) */* 刪除一個(gè)學(xué)生的信息,并且打印 */return 0;26實(shí)例關(guān)鍵點(diǎn)分析int insert(char * name, int id, int score)/* 分配一個(gè)struct std結(jié)構(gòu)對(duì)象 */* 將參數(shù)賦值到結(jié)構(gòu)對(duì)應(yīng)的成員中 */return 1; /* 正確完成操作,返回1 */27實(shí)例關(guān)鍵點(diǎn)分析int remo

7、ve(int id, struct std * res)/* 根據(jù)id找到該學(xué)生的信息結(jié)點(diǎn) */* 將該結(jié)點(diǎn)從鏈表上取下 */* 使用res保存該節(jié)點(diǎn) */* 釋放該結(jié)點(diǎn)所占用的內(nèi)存 */return 1; /* 成功操作返回1 */ 28綜合實(shí)例(1)實(shí)現(xiàn)print函數(shù)對(duì)其遍歷打印鏈表(2)實(shí)現(xiàn)destroy函數(shù)釋放每一個(gè)鏈表節(jié)點(diǎn)(3)實(shí)現(xiàn)search函數(shù)查找鏈表中的元素(4)實(shí)現(xiàn)一個(gè)升級(jí)版的insert將元素按順序插入(5)實(shí)現(xiàn)一個(gè)升級(jí)版的search函數(shù)按順序查找(6)實(shí)現(xiàn)get_count函數(shù)得到鏈表元素個(gè)數(shù)29綜合實(shí)例兩個(gè)擴(kuò)展函數(shù):(1)實(shí)現(xiàn)一個(gè)鏈表排序函數(shù),使用冒泡排序的方法。(2

8、)遍歷一個(gè)鏈表,找到鏈表的中點(diǎn)節(jié)點(diǎn)。(3)尋找某一個(gè)節(jié)點(diǎn)之前的那個(gè)節(jié)點(diǎn)30類(lèi)malloc函數(shù)calloc函數(shù)void *calloc( size_t num, size_t size ); relloc函數(shù)void *realloc(void *mem_address, unsigned int newsize); 31綜合實(shí)例實(shí)現(xiàn)一個(gè)可變的數(shù)組,從一個(gè)鍵盤(pán)輸入若干個(gè)數(shù)字,以-1結(jié)尾。并將其逆序輸出。提示:作為數(shù)組的緩沖區(qū)的大小是固定的,當(dāng)讀取的數(shù)字的數(shù)目超過(guò)數(shù)組大小的時(shí)候需要使用realloc函數(shù)擴(kuò)展緩沖區(qū)數(shù)組。32綜合實(shí)例實(shí)現(xiàn)一個(gè)realloc函數(shù)33動(dòng)態(tài)內(nèi)存分配進(jìn)階深入理解動(dòng)態(tài)分配內(nèi)存的

9、內(nèi)部機(jī)制34堆和棧代碼段數(shù)據(jù)段環(huán)境變量和命令行參數(shù)棧堆進(jìn)程地址空間35malloc函數(shù)的機(jī)制分配原則最先適合分配方法malloc內(nèi)部調(diào)用sbrk()系統(tǒng)調(diào)用一個(gè)進(jìn)程使用一個(gè)堆,所有內(nèi)存由操作系統(tǒng)管理問(wèn)題:如果申請(qǐng)一個(gè)內(nèi)存并沒(méi)有釋放,當(dāng)進(jìn)程結(jié)束運(yùn)行的時(shí)候,會(huì)造成內(nèi)存泄露么嗎?36malloc函數(shù)的實(shí)現(xiàn)內(nèi)存控制塊結(jié)構(gòu)定義:struct mem_control_block int is_available; /* 該塊是否可用 */ int size; /* 該塊的大小 */; 37malloc函數(shù)的實(shí)現(xiàn)兩個(gè)重要的全局變量堆底,分配塊的第一塊:void *managed_memory_start;堆

10、頂,分配塊的最后一塊void *last_valid_address; 38malloc代碼分解函數(shù)的參數(shù):void *malloc(long numbytes) numbytes是要申請(qǐng)的字節(jié)數(shù),但是并不包括內(nèi)存控制塊結(jié)構(gòu),也就是說(shuō)我們實(shí)際需要的空間是numbytes + sizeof(struct mem_control_block)39malloc代碼分解幾個(gè)重要的局部變量:void *current_location; struct mem_control_block *current_location_mcb;void *memory_location;40malloc代碼分解重要的

11、語(yǔ)句:numbytes = numbytes + sizeof(struct mem_control_block); /* 得到完整的需要空間,用戶(hù)需要的空間 + 內(nèi)存控制塊結(jié)構(gòu) */current_location = managed_memory_start; /* 從內(nèi)存塊隊(duì)列的頭開(kāi)始遍歷整個(gè)內(nèi)存隊(duì)列 */41malloc代碼分解while(current_location != last_valid_address) while(current_location != last_valid_address) current_location_mcb = current_location

12、_mcb = (struct mem_control_block(struct mem_control_block * *)current_location; )current_location; if(current_location_mcb-is_available)if(current_location_mcb-is_available) if(current_location_mcb-size = numbytes)if(current_location_mcb-size = numbytes) current_location_mcb-current_location_mcb-is_

13、available = 0;is_available = 0; memory_location = current_location;memory_location = current_location; break; break; current_location = current_location + current_location = current_location + current_location_mcb-size;current_location_mcb-size; 42malloc代碼分解如果現(xiàn)有的內(nèi)存塊不能滿(mǎn)足需要:if(! memory_location) sbrk(

14、numbytes); memory_location = last_valid_address; last_valid_address = last_valid_address + numbytes; current_location_mcb = memory_location; current_location_mcb-is_available = 0; current_location_mcb-size = numbytes;43malloc代碼分解memory_location = memory_location + sizeof(struct mem_control_block); /

15、* 返回給用戶(hù)可用內(nèi)存的地址,跳過(guò)內(nèi)存控制塊結(jié)構(gòu) */ return memory_location; /* 返回 */ 44sbrk系統(tǒng)調(diào)用malloc代碼大部分都由庫(kù)來(lái)完成,為什么還要有這個(gè)系統(tǒng)調(diào)用?這個(gè)系統(tǒng)調(diào)用做了什么?為什么只有內(nèi)存增加的時(shí)候需要系統(tǒng)干預(yù)?現(xiàn)代操作系統(tǒng)的存儲(chǔ)機(jī)制45free函數(shù)的實(shí)現(xiàn)void free(void *firstbyte)struct mem_control_block *mcb;mcb = firstbyte -sizeof(struct mem_control_block); mcb-is_available = 1; /* 這一步是最關(guān)鍵的 */ret

16、urn; 46free機(jī)制總結(jié)并不是真正的釋放,只是將內(nèi)存塊標(biāo)記為可用。問(wèn)題1:釋放內(nèi)存后,系統(tǒng)顯示的可用內(nèi)存數(shù)會(huì)發(fā)生改變嗎?問(wèn)題2:釋放的內(nèi)存還可以引用嗎?47非常規(guī)使用(1)當(dāng)申請(qǐng)0個(gè)字節(jié)時(shí)會(huì)出現(xiàn)什么情況例如:int *p;p = (int *)malloc(0);(2)釋放一個(gè)非動(dòng)態(tài)內(nèi)存申請(qǐng)的空間例如:int array10, *p;p = array; free(p);48兩種內(nèi)存分配的比較動(dòng)態(tài)分配內(nèi)存和非動(dòng)態(tài)分配內(nèi)存的比較動(dòng)態(tài)分配內(nèi)存動(dòng)態(tài)分配內(nèi)存非動(dòng)態(tài)分配內(nèi)存非動(dòng)態(tài)分配內(nèi)存大小在編譯時(shí)確定大小在運(yùn)行時(shí)確定由編譯器分配由操作系統(tǒng)參與分配分配在數(shù)據(jù)段和棧內(nèi)在堆內(nèi)由操作系統(tǒng)自動(dòng)釋放手動(dòng)顯式

17、釋放49memset函數(shù)概念如果需要將一塊內(nèi)存設(shè)置為同一個(gè)值的時(shí)候,需要使用memset函數(shù)。例如:分配一個(gè)緩沖區(qū),將該緩沖區(qū)內(nèi)的值清零50memset函數(shù)原形void memset(void *s, int n, size_t size);s:需要設(shè)置內(nèi)存的首地址n:需要被設(shè)置的值size:需要設(shè)置的字節(jié)數(shù)51memset函數(shù)實(shí)例#include int main()char s10;memset(void *)s, a, 10);s10 = 0;printf(“%sn”, s);return 0; 輸出結(jié)構(gòu)為:aaaaaaaaa52綜合實(shí)例使用memset函數(shù)和malloc函數(shù)實(shí)現(xiàn)一個(gè)ca

18、lloc函數(shù)53memset函數(shù)實(shí)例#include int main()char s10;memset(void *)s, a, 10);s10 = 0;printf(“%sn”, s);return 0; 輸出結(jié)構(gòu)為:aaaaaaaaa54memcpy函數(shù)概念當(dāng)需要在兩塊內(nèi)存之間進(jìn)行數(shù)據(jù)拷貝的時(shí)候需要使用memcpy函數(shù)其原形為:void * memcpy(void *dest, const void * src, size_t n);dest:復(fù)制到目的地址src:復(fù)制的源地址n:需要復(fù)制的字節(jié)數(shù)55memcpy函數(shù)實(shí)例#include int main()char s = “hello

19、”, d10;memcpy(d, s, 5);d5 = 0;printf(“%s”, d);return 0;運(yùn)行結(jié)果:hello56替代函數(shù)void bzero(void *s, size_t n);void bcopy(void * dest, const void * src, size_t n);57其它內(nèi)存塊操作的函數(shù)memccpy(拷貝內(nèi)存內(nèi)容) 定義函數(shù) void * memccpy(void *dest, const void * src, int c,size_t n);函數(shù)說(shuō)明 memccpy()用來(lái)拷貝src所指的內(nèi)存內(nèi)容前n個(gè)字節(jié)到dest所指的地址上。與memcpy()不同的是,memccpy()會(huì)在復(fù)制時(shí)檢查參數(shù)c是否出現(xiàn),若是則返回dest中值為c的下一個(gè)字節(jié)地址。返回值為0表示在src所指內(nèi)存前n個(gè)字節(jié)中沒(méi)有值為c的字節(jié)。58 其它內(nèi)存塊操作的函數(shù)memcmp(比較內(nèi)存內(nèi)容) 相關(guān)函數(shù) bcmp,定義函數(shù) int memcmp (const void *s1,const void *s2,size_t n);函數(shù)說(shuō)明 memcmp()用來(lái)比較s1和s2所指的內(nèi)存區(qū)間前n

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論