C語言查缺補漏(六)記憶體空間,指標
忽略點六:記憶體空間,指標
介紹記憶體前,我們首先要知道一個由C/C++編譯的程式佔用的記憶體分為哪幾個部分:
——棧記憶體:C語言程式在編譯時會被分配到記憶體的一片有限的連續區域,這部分記憶體會用於儲存區域性變數(函式中宣告的變數),這部分連續區域被成為棧記憶體,又編譯器自動分配和釋放
——堆記憶體:一般由程式設計師分配和釋放,若程式設計師沒有釋放,則可能在程式結束時由作業系統回收(並不一定)。注意它與資料結構中的堆是兩種東西!!
——全域性區(靜態區,static):程式的全域性變數和靜態變數都存放在這裡, 初始化存放在一塊區域,未初始化的放在相鄰的另一塊區域(BSS),程式結束後由系統釋放。注意!它既不是棧記憶體,也不是堆記憶體!
——文字常量區:也叫字面量池區。常量字串就是放在這裡,又系統釋放。
——程式程式碼區:存放函式體的區域
以下程式碼大家理解一手:
int a = 1; //全域性初始化區 int b; //全域性未初始化區 int main() { char s[] = "abc"; //棧區 char *p = "abc"; //“abc”在文字常量區(“abc”不是變數,也不是指標變數),p在棧區 static c = 0; //全域性初始化區 char *q = (char *) malloc (sizeof(char)); //q為棧區,申請的內容為堆區 }
關於棧記憶體與堆記憶體:
——棧記憶體:記憶體大小由系統預先設定,且是一塊連續的記憶體空間,如果超出範圍就是造成棧溢位,由於是系統分配的,所以速度較快,但程式猿無法控制。
——堆記憶體:記憶體大小由程式猿手動申請,不一定連續,無記憶體範圍限制(當然啦,肯定不能超過系統的有效記憶體),由於是程式猿分配的,一般速度較慢,但是用起來方便。(當然,如果使用不當的話,會造成嚴重的記憶體洩漏!!!而棧記憶體由於編譯器自動回收記憶體,所以不會出現洩漏問題)
我們由上邊知道了堆記憶體是需要程式猿申請和釋放的。那麼通過什麼方法申請呢?用什麼標頭檔案呢?
——關於標頭檔案,sodlib.h標頭檔案與malloc.h都有封裝的相關申請與釋放堆記憶體的函式,所以兩個選擇任意一個即可
——關於方法,申請有兩個函式
一個是malloc函式,它的格式為:
int *p = (int *) malloc (n * sizeof (int));
sizeof (int)表示n個整形變數所需記憶體空間大小
malloc (sizeof (int))表示申請該大小的記憶體空間,返回值為void型的指標
(int *)表示強制轉換成int型別的指標
另一個是calloc函式,它個格式為:
int *p = (int *) calloc (n, sizeof(int));
該程式碼意義同malloc一致,至於兩者的區別,malloc申請後不初始化,兒calloc申請後全部初始化為0
——釋放有一個函式free,它的用法如下
free(p); //將p所指向的堆記憶體空間釋放回系統
p = NULL; //為避免錯誤使用p指標碰觸已釋放的記憶體,應設定為 p = NULL
以上就是記憶體空間的申請和釋放,可能會有童鞋說還有new,delete,這些屬於C++中的內容,等到C++查缺補漏時再總結~
前一篇博文探究了指標作參的情況,這篇博文來研究一下指標的指標
廢話不多說,上程式碼:
int a = 1;
int *p = &a;
int **q = &p;
在上面程式碼中:
對於第一行來說:a是int型別變數
對於第二行來說:p為變數a的地址(&a),而*p為a的值
對於第三行來說,q為指標變數p的地址,也就是&p,而*q為p的值,也就是a的地址(&a)
因此:*q = p = &a q = &p
就是醬紫~
如果有寫的不對或者不全面的地方 請指正! 謝謝~