c語言記憶體的理解
首先如圖記憶體分四區
- 棧區(stack)—由編譯器自動分配釋放,存放函式的引數值,區域性變數的值等。其操作方式類似於資料結構中的棧。
- 堆區(heap)—一般由程式設計師分配釋放,若程式設計師不釋放,程式結束時可能由OS回收。注意它與資料結構中的堆是兩回事,分配方式倒是類似於連結串列
- 全域性區(靜態區)(static)—全域性變數和靜態變數的儲存是放在一塊的,初始化的全域性變數和靜態變數在一塊區域,未初始化的全域性變數和未初始化的靜態變數在相鄰的另一塊區域。 程式結束後由系統釋放。
- 常量區—常量字串就是放在這裡的,直到程式結束後由系統釋放。
- 程式碼區—存放函式體的二進位制程式碼。
注:malloc函式的實質體現在,它有一個將可用的記憶體塊連線為一個長長的列表的所謂空閒連結串列。呼叫malloc函式時,它沿連線表尋找一個大到足以滿足使用者請求所需要的記憶體塊。然後,將該記憶體塊一分為二(一塊的大小與使用者請求的大小相等,另一塊的大小就是剩下的位元組)。接下來,將分配給使用者的那塊記憶體傳給使用者,並將剩下的那塊(如果有的話)返回到連線表上。呼叫free函式時,它將使用者釋放的記憶體塊連線到空閒鏈上。到最後,空閒鏈會被切成很多的小記憶體片段,如果這時使用者申請一個大的記憶體片段,那麼空閒鏈上可能沒有可以滿足使用者要求的片段了。於是,malloc函式請求延時,並開始在空閒鏈上翻箱倒櫃地檢查各記憶體片段,對它們進行整理,將相鄰的小空閒塊合併成較大的記憶體塊。如果無法獲得符合要求的記憶體塊,malloc函式會返回NULL指標,因此在呼叫malloc動態申請記憶體塊時,一定要進行返回值的判斷。
下面就是對於堆區的建立
1.malloc 開闢一塊記憶體用來儲存
void *malloc(unsighed int size)
2.calloc 開闢n個長度為size的連續空間
void *calloc (unsigned n ,unsigned size)
3.recalloc 就是對於已經開闢的儲存空間進行再次規劃
void *realloc(void *p,unsigned int size)
4.free 釋放記憶體
void free(void *p)
學完這些雖然現在只學過c但是以我現在對於計算機的理解真的佩服竟然能對記憶體直接進行讀寫呼叫
這塊說一下void指標型別主要用於儲存地址,類似於一個不知道是什麼型別的空的指標變數
全域性區的理解
#include<stdio.h>
char * getStr1();
char * getStr2();
char * getStr1()
{
char *p1 = "abcdefg";
return p1;
}
char * getStr2()
{
char *p2 = "abcdefg2";
return p2;
}
void main()
{
char *p1 = NULL;
char *p2 = NULL;
p1 = getStr1();
p2 = getStr2();
printf("p1:%s,p2:%s\n",p1,p2);
printf("p1:%d,p2:%d\n",p1,p2);
return ;
}
#include<stdio.h>
char * getStr1();
char * getStr2();
char * getStr1()
{
char *p1 = "abcdefg2";
return p1;
}
char * getStr2()
{
char *p2 = "abcdefg2";
return p2;
}
void main()
{
char *p1 = NULL;
char *p2 = NULL;
p1 = getStr1();
p2 = getStr2();
printf("p1:%s,p2:%s\n",p1,p2);
printf("p1:%d,p2:%d\n",p1,p2);
return ;
}
為什麼會有這種情況呢?
我們從頭分析
首先c++編輯器從main函式進入、
先來定義
p1,p2兩個變數
下面執行getstr1
將字串寫入全域性區
下面再次開闢一塊記憶體將函式getser1的p1(兩個p1名字一樣其實不同)
同時將字串首地址寫入getstr1的p1指向的記憶體中
下面將getstr1的p1中存的地址傳給主函式中的p1
執行完p1後釋放記憶體,然後執行getstr2,進行壓棧
之後getstr2執行,但是其實c++在編譯時對我們的程式進行了優化(詞法 語法 句法分析),如果p1,p2的字串一樣呢麼他就會自動只在全域性區寫入一次,如果不同才會寫兩次
總結
1.指標指向誰 就把是誰的地址賦值給指標
2.指標變數和它所值得記憶體空間的變數是兩個概念
棧區的理解