周立功教授數(shù)年之心血之作《程序設(shè)計(jì)與數(shù)據(jù)結(jié)構(gòu)》,電子版已無償性分享到電子工程師與高校群體,在公眾號(hào)回復(fù)【程序設(shè)計(jì)】即可在線閱讀。書本內(nèi)容公開后,在電子行業(yè)掀起一片學(xué)習(xí)熱潮。經(jīng)周立功教授授權(quán),本公眾號(hào)特對(duì)本書內(nèi)容進(jìn)行連載,愿共勉之。
第一章為程序設(shè)計(jì)基礎(chǔ),本文為1.9.1 malloc()函數(shù)和1.9.2 calloc()函數(shù)。
》》》》 1.9 動(dòng)態(tài)分配內(nèi)存
首先回顧一下內(nèi)存分配,所有程序都必須預(yù)留足夠的內(nèi)存存儲(chǔ)程序使用的數(shù)據(jù),這些內(nèi)存中有些是自動(dòng)分配的。比如,聲明“int iNum;”為一個(gè)int類型的值預(yù)留了足夠的內(nèi)存,或顯式指定分配一定數(shù)量的內(nèi)存,“int pData[20];”聲明預(yù)留了20個(gè)內(nèi)存位置,每個(gè)位置存儲(chǔ)的是int類型的值。聲明還為內(nèi)存提供了標(biāo)識(shí)符,因此可以使用iNum或pData識(shí)別數(shù)據(jù)。靜態(tài)數(shù)據(jù)在程序載入內(nèi)存時(shí)分配的,自動(dòng)數(shù)據(jù)是在程序執(zhí)行時(shí)分配的,并在程序離開時(shí)銷毀。但C能做的遠(yuǎn)不止這些,可以在程序運(yùn)行時(shí)請(qǐng)求所需要的內(nèi)存大小。
程序在運(yùn)行時(shí)分配的內(nèi)存空間稱之為“堆”的存儲(chǔ)池,雖然計(jì)算機(jī)在硬件上不直接支持堆,但C函數(shù)庫(stdlib.h)分別提供了用于動(dòng)態(tài)內(nèi)存分配和釋放的函數(shù)malloc()和free(),即在運(yùn)行時(shí)根據(jù)需要?jiǎng)?chuàng)建一個(gè)存儲(chǔ)單元,在不需要時(shí)釋放。
》》》 1.9.1 malloc()函數(shù)
malloc()函數(shù)原型如下:
void *malloc(unsigned int size);
其中,void *表示該函數(shù)是指針函數(shù),size為所需內(nèi)存的字節(jié)數(shù),可以用sizeof運(yùn)算符計(jì)算每個(gè)元素所需要的空間數(shù)量和所有元素需要內(nèi)存的字節(jié)數(shù)。如果分配成功,雖然malloc()不會(huì)為分配的內(nèi)存賦名,但它確實(shí)返回了動(dòng)態(tài)分配內(nèi)存塊的首字節(jié)地址。因此可以將該地址賦給一個(gè)指針變量,并使用指針變量訪問這塊內(nèi)存。如果分配不成功或內(nèi)存不足,則返回空指針NULL。因此在使用它返回的指針之前,一定要先檢查返回值,否則可能會(huì)導(dǎo)致程序非正常終止。比如:
int *pi = malloc(sizeof(int));
if(pi != NULL){
// 指針沒有問題
}else{
// 無效的指針
}
malloc()函數(shù)可用于返回指向數(shù)組的指針、指向結(jié)構(gòu)的指針等,所以通常該函數(shù)的返回值會(huì)被強(qiáng)制轉(zhuǎn)換為匹配的類型,但從C99版本開始,void *類型的指針不需要強(qiáng)制轉(zhuǎn)換地賦給所有的指針類型變量。
當(dāng)編寫程序時(shí),常常很難為數(shù)組估計(jì)合適的大小,較為方便的做法是等到程序運(yùn)行時(shí),再來確定數(shù)組的實(shí)際大小。其方法是用malloc()在程序執(zhí)行期間為數(shù)組分配空間,然后通過指向數(shù)組第一個(gè)元素的指針訪問數(shù)組。假設(shè)正在編寫的程序需要n個(gè)整數(shù)構(gòu)成的數(shù)組,這里的n可以在程序執(zhí)行期間計(jì)算出來。首先需要聲明指針變量:
int * pi, n;
一旦n的值已知,就讓程序調(diào)用malloc()函數(shù)為數(shù)組分配存儲(chǔ)空間:
pi = malloc(n * sizeof(int));
if(pi == NULL) return -1;
當(dāng)pi指向分配動(dòng)態(tài)分配的內(nèi)存塊時(shí),就可以忽略pi是指針的事實(shí),將它作為數(shù)組名使用,這是C語言數(shù)組和指針形成緊密關(guān)系的所帶來的便利。由于數(shù)組名是該數(shù)組首元素的地址,如果讓pi指向這個(gè)塊的首元素,便可以象使用數(shù)組名一樣使用它。即可以使用pi[0]訪問該塊的首元素,pi[1]訪問第2個(gè)元素,以此類推。比如,使用下列循環(huán)對(duì)pi指向的數(shù)組進(jìn)行初始化:
for(i = 0; i 《 n; i++) pi[i] = 0;
動(dòng)態(tài)內(nèi)存分配可以提供更多的靈活性,比如:
char *pcStr;
char *pcStr = malloc(strlen(“OK!”) + 1);
strcpy(pcStr, “OK!”);
在這里,使用strlen()計(jì)算字符串的長度,一定要記得加上結(jié)束符NUL。為何不用sizeof呢?因?yàn)閟zieof會(huì)返回?cái)?shù)組和指針的長度,而不是字符串的長度。
》》》 1.9.2 calloc()函數(shù)
雖然可以用malloc()函數(shù)為數(shù)組分配內(nèi)存,但C語言提供了一種更好用的calloc()函數(shù),其函數(shù)原型如下:
void *calloc(size_t nmenb, size_t size);
calloc()函數(shù)為nmemb個(gè)元素的數(shù)組分配內(nèi)存空間,其中,每個(gè)元素的長度都是size個(gè)字節(jié)。如果要求的空間無效,那么此函數(shù)返回指針。在分配了內(nèi)存之后,calloc()函數(shù)會(huì)通過將所有位設(shè)置為0的方式進(jìn)行初始化。比如,調(diào)用calloc()函數(shù)為n個(gè)整數(shù)的數(shù)組分配存儲(chǔ)空間,且保證所有整數(shù)初始化為0。比如:
pi = calloc(n, sizeof(int));
因?yàn)閏alloc()函數(shù)會(huì)清楚分配的內(nèi)存,而malloc()函數(shù)不會(huì),所以可以調(diào)用以“1”作為第一個(gè)實(shí)參的calloc()函數(shù),為任何類型的數(shù)據(jù)項(xiàng)分配空間。比如:
struct point{ int x, y;} *pi;
pi = calloc(1, sizeof(struct point));
在執(zhí)行此語句后,pi將指向一個(gè)結(jié)構(gòu)體,且此結(jié)構(gòu)體的成員x和y都會(huì)被設(shè)為0。
-
周立功
+關(guān)注
關(guān)注
38文章
130瀏覽量
37712 -
大數(shù)據(jù)
+關(guān)注
關(guān)注
64文章
8908瀏覽量
137654 -
malloc
+關(guān)注
關(guān)注
0文章
53瀏覽量
75
原文標(biāo)題:周立功:動(dòng)態(tài)分布內(nèi)存——malloc()函數(shù)與calloc()函數(shù)
文章出處:【微信號(hào):ZLG_zhiyuan,微信公眾號(hào):ZLG致遠(yuǎn)電子】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論