1. 程式人生 > >C語言查缺補漏(六)記憶體空間,指標

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

​ 就是醬紫~

如果有寫的不對或者不全面的地方 請指正! 謝謝~