内存结构
0.代碼段:存放函數二進制代碼的區域;
1.RO DATA只讀數據段(靜態區域):存儲不可改變的常量,無論局部還是全局的;
2.RW DATA讀寫數據段(靜態區域):存儲可改變的,全局變量(前提是定義的時候直接初始化),或者用static修飾的局部變量(也需要先初始化):static只在當前的{}程序代碼段中有效;
3.BBS未初始化數據區(靜態區域):分為全局和局部的區別,都會放在這里,只有初始化后,才會放到對應的棧或者RW,RO DATA,(定義的時候即初始化除外)靜態區域的未初始化的變量存放在這里,存放未初始化的變量平時沒有的,在程序運行時動態生成(所以平時exe里面不包含這個的大小),需編譯器明確指定大小(因為未初始化);
4.函數內部局部變量,不用static或const申明的,都放在棧上,棧上的數據會自動釋放。主要存儲:局部變量,形參,返回值,變量空間在函數開始前開辟,結束后回收;
5.用malloc,free的都放在堆上面,可以隨時申請,需要主動釋放:
應用:
const char *ptrConst = "fdsfadf"; 字符串常量放在RO DATA,而加了const修飾的指針,由于是全局的,肯定在靜態區域(RO DATA),但是ptrConst指向的內容不可改變,本身指向的地址是可變的,所以ptrConst放在RW DATA (這里是指全局情況,如果是局部這么定義,ptrConst會存儲在棧上面;
const char const *ptrConst = "fdsfadf"; 這樣兩者都會放在RO DATA;
const char a[] = "fsdfds"; 數組不同于指針,兩個都放在RO DATA,可以認為數組完全等價于"fsdfsds",不可改變;
const指針: const char *p = XXX p可變,*p是const;
const (char *)p = XXX p是const,*p可變;
const char * const p = xxx 最強約束,都是const 即const離那個近,哪個就是const了,但還可以直接放在后面:
char const *p = XXX //p可變,*p是const (char ) const p = XXX //p是const,p可變
char * const p = XXX///p是const,p可變
char const * const p = xxx //最強約束,都是const 沿著號劃一條線,如果const位于的左側,則const就是用來修飾指針所指向的變量,即指針指向為常量;
如果const位于的右側,const就是修飾指針本身,即指針本身是常量。可以根據這個規則來看上面聲明的實際意義,相信定會一目了然。 注意:
①用const定義的全局變量,如果要存儲,必須存儲函數也指明是const才行,否則是無法從外部讀取的,只能引用。
②只讀數據定義的時候一般都是做完整的初始化,否則多余未初始化的空間也是無法適用的,因為在RO DATA里面
6.堆和棧:能不靈活就不靈活,這樣效率相對會比較高一點
大小:棧是一個固定大小的內存空間,超過的話會提示over flow,堆則是鏈表,和內存大小有關;
效率:堆更加靈活,相對效率就會低很多,棧比較死板,但是效率高(堆由操作系統維護,棧是程序維護的)
棧是機器系統提供的數據結構,計算機會在底層對棧提供支持:分配專門的寄存器存放棧的地址,壓棧出棧都有專門的指令執行,這就決定了棧的效率比較高。
堆則是C/C++函數庫提供的,它的機制是很復雜的,例如為了分配一塊內存,庫函數會按照一定的算法(具體的算法可以參考數據結構/操作系統)在堆內存中搜索可用的足夠大小的空間,如果沒有足夠大小的空間(可能是由于內存碎片太多),就有可
能調用系統功能去增加程序數據段的內存空間,這樣就有機會分到足夠大小的內存,然后進行返回。顯然,堆的效率比棧要低得多。
注意:
(1)堆:char *s1=”hellow tigerjibo”;是在編譯是就確定的 (2)棧:char s1[]=”hellow tigerjibo”;是在運行時賦值的;用數組比用指針速度更快一些,指針在底層匯編中需要用edx寄存器中轉一下,而數組在棧上讀取。 同樣是只讀數據區的數據,用數組來獲取會比用指針快一點;
(2)棧:在函數調用時,第一個進棧的主函數中后的下一條語句的地址,然后是函數的各個參數,參數是從右往左入棧的,然后是函數中的局部變量。注:靜態變量是不入棧的。
當本次函數調用結束后,局部變量先出棧,然后是參數,最后棧頂指針指向最開始存的地址,也就是主函數中的下一條指令,程序由該點繼續執行;
(3)堆:一般是在堆的頭部用一個字節存放堆的大小,后面直接存儲內容,只要記住地址就可以用啦,比較靈活。
堆是操作系統存儲空閑的內存空間地址的一個鏈表,每次申請后,從鏈表中找出空間》=申請大小的節點,
釋放出來給程序用(多出來的部分再在鏈表上面生成新的節點),一般空間首部會存儲本次分配的大小,這樣方便free的時候,進行空間釋放,釋放后再次作為節點存放到鏈表中。 說明:對于堆來講,頻繁的new/delete勢必會造成內存空間的不連續,從而造成大量的碎片,使程序效率降低。對于棧來講,則不會存在這個問題,
?
總結
- 上一篇: “make -n”和 “+comman
- 下一篇: 硬件板卡调试