<button id="6ymue"><menu id="6ymue"></menu></button>
    • <s id="6ymue"></s>
    • 美章網 資料文庫 C語言動態存儲范文

      C語言動態存儲范文

      本站小編為你精心準備了C語言動態存儲參考范文,愿這些范文能點燃您思維的火花,激發您的寫作靈感。歡迎深入閱讀并收藏。

      C語言動態存儲

      一、動態存儲管理的實現

      C語言動態存儲管理由一組標準庫函數實現,其原型在標準文件<stdlib.h>里描述,需要用這些功能時應包含這個文件。與動態存儲分配有關的函數共有四個:

      1)存儲分配函數malloc。其函數原型是:voidmalloc(unsignedintsize);其作用是在內存的動態存儲區中分配一個長度為size的連續空間。這里的size是一個無符號整型,malloc的返回值為void類型,它分配一片能存放大小為size的數據的存儲塊,返回指向該存儲塊起始地址的指針值;如果不能滿足申請(例如內存不足)就返回空指針NULL。所以在調用該函數時應該檢測返回值是否為NULL并執行相應的操作。

      2)帶計數和清0的動態存儲分配函數calloc。其函數原型是:

      void*calloc(unsignedn,unsignedsize);參數size意指數據元素的大小,n指要存放的元素個數。calloc將分配一塊存儲,其大小足以存放n個大小各為size的元素,分配之后還把存儲塊里全部清0(初始化為0值)。如果分配不成功就返回NULL。

      3)動態存儲釋放函數free。其原型是:voidfree(void*p);其作用是釋放指針p所指的內存區,使這部分內存區能被其它變量使用。p是調用calloc或malloc函數時返回的值。free函數無返回值。如果當時p的值是空指針,free就什么也不做。注意,調用free(p)不會改變p的值(在函數里不可能改變值參數p),但被p指向的內存區的內容卻可能變了(可能由于存儲管理的需要)。釋放后不允許再通過p去訪問已釋放的區,否則也可能引起災難性后果。由于內存區域有限,每個程序都應盡量節省資源。當所分配的內存區域不再使用時,就應及時將它釋放,以便其它的變量或者程序使用,這應該成為習慣。這時就要用到free函數。

      4)分配調整函數realloc。其函數原型是:void*realloc(void*p,unsignedn);其作用是更改以前的存儲分配。在調用realloc時,指針變量p的值必須是調用calloc或malloc函數時返回的值,參數n表示現在需要的存儲塊大小。realloc在無法滿足新要求時返回NULL,同時也保持p所指的存儲塊的內容不變。如果能夠滿足要求,realloc就返回一片存放大小為n的數據的存儲塊,并保證該塊的內容與原塊一致:如果新塊較小,其中將存放著原塊里大小為n的范圍內的那些數據;如果新塊更大,原有數據存在新塊的前面一部分里,新增的部分不自動初始化。如果分配成功,原存儲塊的內容就可能改變了,因此不允許再通過p來使用它。請注意:通過動態分配得到的塊是一個整體,只能作為一個整體管理。在調用free(p)或者realloc(p,……)時,p當時的值必須是以前通過調用存儲分配函數得到的,絕不能對指在動態分配塊里其它位置的指針調用這兩個函數,更不能對并不指向動態分配塊的指針使用它們,那樣做的后果不堪設想。

      二、使用動態存儲管理的要點

      1)必須檢查分配的成功與否。常的解決辦法是,在使用內存之前檢查指針是否為NULL。如果指針p是函數的參數,那么在函數的入口處用assert(p!=NULL)進行檢查。如果是用malloc或new來申請內存,則用以下語句來防錯:if((p=(...*)malloc(…))==NULL){……/*對分配未成功情況的處理*/}。2)系統對動態分配塊的使用不做任何檢查。編程序的人需要保證使用的正確性,絕不可以超出實際存儲塊的范圍進行訪問。例如在使用數組時經常發生下標“多1”或者“少1”的操作。這種越界訪問可能造成大災難。3)一個動態分配塊的存在期并不依賴于分配這個塊的地方。在一個函數里分配的存儲塊的存在期與該函數的執行期無關。函數結束時不會自動回收這一存儲塊,要回收這種塊,唯一的方法就是通過free釋放(完全由寫程序的人控制)。4)如果在函數里分配了一個存儲塊,并用局部變量指向它,在這個函數退出前就必須考慮如何處理這個塊。如果這個塊已經沒用了,那么就應該把它釋放掉;如果這個塊還有用(其中保存著有用的數據),那么就應該把它的地址賦給存在期更長的變量(例如全局變量),或者把這個地址作為函數返回值,讓調用函數的地方去管理它。5)其它情況也可能造成存儲塊丟失。例如給一個指向動態存儲塊的指針賦其它值,如果此前沒有其它指針指向這個塊,此后就再也無法找到它了。如果一個存儲塊丟失了,在這個程序隨后的運行中,將永遠不能再用這個存儲塊所占的存儲。6)計算器系統里的存儲管理分很多層次。一個程序運行時,操作系統分給它一部分存儲,供它保存代碼和數據。其數據區里包括一塊動態存儲區,由這個程序的動態存儲管理系統管理。該程序運行中的所有動態存儲申請都在這塊空間里分配,釋放就是把不用的存儲塊交還程序的動態存儲管理系統。一旦這個程序結束,操作系統就會收回它占用的所有存儲空間。

      三、關于動態調整策略

      我們可以將一個動態分配的,能存儲許多元素的存儲塊可以看成一個“數組”,要實現這樣一個能在使用中根據需要增長的“動態”數組,需要考慮所采用的增長策略。

      一個簡單而直接的想法是設定一個增量,例如10,一旦存儲區滿時就把存儲區擴大10個單元。仔細考慮和計算會發現這樣做有很大的缺限。實際中對存儲量的需要常常是逐步增加的。一般說,在遇到存儲區滿時,實際上需要另外分配一塊更大的存儲區,并需要把原塊里已有的元素復制到新塊里。realloc完成這種操作的代價通常與原有的元素個數成正比。

      四、函數、指針和動態存儲

      如果需要在函數里處理一組數據,并把處理結果反應到調用函數的地方,最合適的辦法就是在函數調用時提供數組的起始位置和元素數目(或者結束位置)。這時函數完全不必知道用的是程序里定義的數組變量,還是動態分配的存儲塊。例如,我們完全可以用如下方式調用篩法函數:intns[1000];intmain(){inti,j;sieve(1000,ns);for(j=1,i=2;i<=n;++i);if(ns[i]==1){printf("%7d%c",i,(j%8?'''''''':''''\n''''));++j;}putchar(''''\n'''');return0;}

      在前一節的篩法程序實例里,我們在主函數里通過動態分配取得存儲,而后調用函數sieve,最后還是由main函數釋放這塊存儲。這樣,分配和釋放的責任位于同一層次,由同一個函數(函數main)完成。這樣做最清晰,易于把握,是最好的處理方案。

      但也存在一些情況,其中不能采用上述做法,例如上面的直方圖程序。程序里定義了一個讀入函數,它需要根據輸入情況確定如何申請動態存儲。這時的動態存儲的申請在被調用函數readscore的內部,該函數完成向存儲塊里填充數據的工作,最后把做好的存儲塊(就像是一個數組)的地址通過返回值送出來。調用函數(main)用類型合適的指針接收這個地址值,而后通過這個指針使用這一存儲塊里的數據。

      首先,這一做法完全正確,因為動態分配的存儲塊將一直存在到明確調用free釋放它為止。雖然上述存儲塊是在函數readscores里面分配的,但它的生命周期(生存期)并不隨該函數的退出而結束。語句:

      scores=readscores(&n);使scores得到函數readscores的運行中申請來并填充好數據的存儲塊,在main里繼續用這個塊是完全沒問題的。當然,采用這種方式,readscores就不應該在退出前釋放該塊。注意:上面的調用除了傳遞有關的數據外,實際上還有存儲管理責任的轉移問題。在readscores把一塊存儲的指針通過返回值送出來時,也把釋放這塊存儲的責任轉交給main。這樣,我們也可以看出前面的程序忽略了一件事情,在那里沒有釋放這一存儲塊。應做的修改就是在main的最后加一個釋放語句(當然,由于main的結束就就是整個程序的結束,未釋放的這塊存儲也不會再有用了。如前所述,在這個程序結束后,操作系統將會回收這個程序占用的全部存儲)。

      現在考慮readscores的設計里的一個問題。在前面的程序里,readscores通過int指針參數(實參應該是一個int變量的地址)傳遞實際讀入數據的個數。另一種可能做法是讓函數返回這一整數值,例如將其原型改成:intreadscores(???);這樣,我們在main里就可以寫如下形式的調用:if(readscores(……)<=0){……}/*產生錯誤信息并結束程序*/(這一寫法使人想起標準庫的輸入函數scanf)。如果這樣設計函數,調用readscores的地方就需要通過實參取得函數里動態分配的存儲塊地址。也就是說,要從參數獲得一個指針值。問題是,這個函數的參數應該如何定義呢?答案與其它情況完全一樣。如果我們想通過實參取得函數里送出來的一個int值,就要把一個int變量的地址送進函數,要求函數間接地給這個變量賦值。同理,現在需要得到一個指針值,就應該通過實參把這種指針變量的地址送進去,讓函數通過該地址給調用時指定的指針變量賦值。這樣,修改后的函數readscores的原型應該是:intreadscores(double**dpp);

      總的說來,我們介紹了指針、函數與動態分配之間的一些關系,并討論了幾種不同的處理技術。只要有可能,在程序里最好使用第一種設計,因為它最清晰,也最不容易出現忘記釋放的情況,如果不得已而采用了其它方式,那么就一定要記得存儲管理責任的交接問題,并在適當的地方釋放動態分配的存儲區。

      摘要:本文探討了C語言的動態存儲管理的實現、使用要點、動態調整策略等方面內容,以其對有關人員提供參考/

      關鍵詞:C語言;動態;存儲;管理。

      所謂動態內存分配就是指在程序執行的過程中動態地分配或者回收存儲空間的分配內存的方法。動態內存分配不像數組等靜態分配方法那樣需要預先分配存儲空間,而是由系統根據程序的需要實時分配,且分配的大小就是程序要求的大小。

      主站蜘蛛池模板: 911香蕉视频| 亚洲欧美综合区自拍另类| 久久久精品国产sm最大网站| 五月天婷婷精品视频| 欧美性猛交一区二区三区| 在线观看一二三区| 亚洲视频在线观看一区| a级毛片免费看| 91精品国产高清久久久久久 | 天天爽夜夜爽人人爽一区二区| 农民工嫖妓50岁老熟女| 一进一出60分钟免费视频| 精品视频一区二区三区在线观看| 欧美丰满熟妇xxxx性ppx人交| 国产精品久线在线观看| 亚洲人成无码网站久久99热国产 | 娇妻之欲海泛舟小强| 免费激情视频网站| HEYZO无码综合国产精品| 永久免费无码网站在线观看| 国产精品青青青高清在线| 亚洲成av人在线视| 欧美xxxxbbb| 日本熟妇色熟妇在线视频播放| 国产乱子伦在线观看不卡| 丰满的寡妇3在线观看 | 最新在线黄色网址| 国产四虎精品8848hh| 中文字幕永久免费视频| 精品国产青草久久久久福利| 天天躁日日躁成人字幕aⅴ| 亚洲片在线观看| jlzzjlzz亚洲jzjzjz| 日韩一品在线播放视频一品免费| 国产v在线播放| www.色午夜| 欧美日韩国产亚洲一区二区三区| 国产私人尤物无码不卡| 久久久久成人精品无码| 精品久久久久久无码人妻蜜桃| 天堂va在线高清一区|