topoic=動態(tài)存儲分配
在數(shù)組一章中,曾介紹過數(shù)組的長度是預(yù)先定義好的, 在整個程序中固定不變。C語言中不允許動態(tài)數(shù)組類型。例如: int n;scanf("%d",&n);int a[n]; 用變量表示長度,想對數(shù)組的大小作動態(tài)說明,這是錯誤的。但是在實際的編程中,往往會發(fā)生這種情況, 即所需的內(nèi)存空間取決于實際輸入的數(shù)據(jù),而無法預(yù)先確定。對于這種問題,用數(shù)組的辦法很難解決。為了解決上述問題,C語言提供了一些內(nèi)存管理函數(shù),這些內(nèi)存管理函數(shù)可以按需要動態(tài)地分配內(nèi)存空間,也可把不再使用的空間回收待用,為有效地利用內(nèi)存資源提供了手段。 常用的內(nèi)存管理函數(shù)有以下三個:
1.分配內(nèi)存空間函數(shù)malloc
調(diào)用形式: (類型說明符*) malloc (size) 功能:在內(nèi)存的動態(tài)存儲區(qū)中分配一塊長度為“size”字節(jié)的連續(xù)區(qū)域。函數(shù)的返回值為該區(qū)域的首地址。 “類型說明符”表示把該區(qū)域用于何種數(shù)據(jù)類型。(類型說明符*)表示把返回值強制轉(zhuǎn)換為該類型指針!皊ize”是一個無符號數(shù)。例如: pc=(char *) malloc (100); 表示分配100個字節(jié)的內(nèi)存空間,并強制轉(zhuǎn)換為字符數(shù)組類型, 函數(shù)的返回值為指向該字符數(shù)組的指針, 把該指針賦予指針變量pc。
2.分配內(nèi)存空間函數(shù) calloc
calloc 也用于分配內(nèi)存空間。調(diào)用形式: (類型說明符*)calloc(n,size) 功能:在內(nèi)存動態(tài)存儲區(qū)中分配n塊長度為“size”字節(jié)的連續(xù)區(qū)域。函數(shù)的返回值為該區(qū)域的首地址。(類型說明符*)用于強制類型轉(zhuǎn)換。calloc函數(shù)與malloc 函數(shù)的區(qū)別僅在于一次可以分配n塊區(qū)域。例如: ps=(struet stu*) calloc(2,sizeof (struct stu)); 其中的sizeof(struct stu)是求stu的結(jié)構(gòu)長度。因此該語句的意思是:按stu的長度分配2塊連續(xù)區(qū)域,強制轉(zhuǎn)換為stu類型,并把其首地址賦予指針變量ps。
3.釋放內(nèi)存空間函數(shù)free
調(diào)用形式: free(void*ptr); 功能:釋放ptr所指向的一塊內(nèi)存空間,ptr 是一個任意類型的指針變量,它指向被釋放區(qū)域的首地址。被釋放區(qū)應(yīng)是由malloc或calloc函數(shù)所分配的區(qū)域:[例7.9]分配一塊區(qū)域,輸入一個學(xué)生數(shù)據(jù)。
main()
{
struct stu
{
int num;
char *name;
char sex;
float score;
} *ps;
ps=(struct stu*)malloc(sizeof(struct stu));
ps->num=102;
ps->name="Zhang ping";
ps->sex='M';
ps->score=62.5;
printf("Number=%d\nName=%s\n",ps->num,ps->name);
printf("Sex=%c\nScore=%f\n",ps->sex,ps->score);
free(ps);
}
本例中,定義了結(jié)構(gòu)stu,定義了stu類型指針變量ps。然后分配一塊stu大內(nèi)存區(qū),并把首地址賦予ps,使ps指向該區(qū)域。再以ps為指向結(jié)構(gòu)的指針變量對各成員賦值,并用printf 輸出各成員值。最后用free函數(shù)釋放ps指向的內(nèi)存空間。 整個程序包含了申請內(nèi)存空間、使用內(nèi)存空間、釋放內(nèi)存空間三個步驟,實現(xiàn)存儲空間的動態(tài)分配。鏈表的概念在例7.9中采用了動態(tài)分配的辦法為一個結(jié)構(gòu)分配內(nèi)存空間。每一次分配一塊空間可用來存放一個學(xué)生的數(shù)據(jù),我們可稱之為一個結(jié)點。有多少個學(xué)生就應(yīng)該申請分配多少塊內(nèi)存空間,也就是說要建立多少個結(jié)點。當(dāng)然用結(jié)構(gòu)數(shù)組也可以完成上述工作,但如果預(yù)先不能準(zhǔn)確把握學(xué)生人數(shù),也就無法確定數(shù)組大小。而且當(dāng)學(xué)生留級、退學(xué)之后也不能把該元素占用的空間從數(shù)組中釋放出來。 用動態(tài)存儲的方法可以很好地解決這些問題。有一個學(xué)生就分配一個結(jié)點,無須預(yù)先確定學(xué)生的準(zhǔn)確人數(shù),某學(xué)生退學(xué), 可刪去該結(jié)點,并釋放該結(jié)點占用的存儲空間。從而節(jié)約了寶貴的內(nèi)存資源。 另一方面,用數(shù)組的方法必須占用一塊連續(xù)的內(nèi)存區(qū)域。 而使用動態(tài)分配時,每個結(jié)點之間可以是不連續(xù)的(結(jié)點內(nèi)是連續(xù)的)。結(jié)點之間的聯(lián)系可以用指針實現(xiàn)。 即在結(jié)點結(jié)構(gòu)中定義一個成員項用來存放下一結(jié)點的首地址,這個用于存放地址的成員,常把它稱為指針域?稍诘谝粋結(jié)點的指針域內(nèi)存入第二個結(jié)點的首地址, 在第二個結(jié)點的指針域內(nèi)又存放第三個結(jié)點的首地址, 如此串連下去直到最后一個結(jié)點。最后一個結(jié)點因無后續(xù)結(jié)點連接,其指針域可賦為0.這樣一種連接方式,在數(shù)據(jù)結(jié)構(gòu)中稱為“鏈表”。
在鏈表中,第0個結(jié)點稱為頭結(jié)點, 它存放有第一個結(jié)點的首地址,它沒有數(shù)據(jù),只是一個指針變量。 以下的每個結(jié)點都分為兩個域,一個是數(shù)據(jù)域,存放各種實際的數(shù)據(jù),如學(xué)號num,姓名name,性別sex和成績score等。另一個域為指針域, 存放下一結(jié)點的首地址。鏈表中的每一個結(jié)點都是同一種結(jié)構(gòu)類型。例如,一個存放學(xué)生學(xué)號和成績的結(jié)點應(yīng)為以下結(jié)構(gòu):
struct stu
{
int num;
int score;
struct stu *next;
}
相關(guān)推薦:
2012年軟考系統(tǒng)分析師考試60天完美復(fù)習(xí)計劃
北京 | 天津 | 上海 | 江蘇 | 山東 |
安徽 | 浙江 | 江西 | 福建 | 深圳 |
廣東 | 河北 | 湖南 | 廣西 | 河南 |
海南 | 湖北 | 四川 | 重慶 | 云南 |
貴州 | 西藏 | 新疆 | 陜西 | 山西 |
寧夏 | 甘肅 | 青海 | 遼寧 | 吉林 |
黑龍江 | 內(nèi)蒙古 |