修飾符與記憶體佈局
1.auto 型別. 1)只能用於修飾區域性變數,表示該變數儲存在棧上 stack. 2)預設的區域性變數,就是aotu型別,所以通常將其省略.
2.register. 只能修飾區域性變數,將記憶體重的變數升級到cpu暫存器中儲存,這樣訪問速度會很快。儲存cpu的變數,速度快但是數量有限,通常用來優化。用於頻繁使用的變數,一般不用。 必須要注意的是,使用register修飾的變數不能去地址值,因為該變數儲存在暫存器,是沒有地址的。
3.extern 用來修飾變數或函式,extern可以置於變數或者函式前,以表示變數或者函式定義在別的檔案中,提示編譯器遇到此變數或函式時在其他模組中尋找其定義。 注意:因為宣告函式沒有函式體(還有以分號結尾),所以在宣告函式的時候可以將extern省略掉。但一般是在標頭檔案(.h檔案)宣告的時候才省略掉extern,如果是在其他c檔案宣告則建議加上extern。 (1)不要在標頭檔案定義全域性變數,全域性變數需要定義在.c檔案,標頭檔案使用extern進行宣告即可。 (2)檔案宣告的函式可以不加extern,且也不要在標頭檔案定義。
4.static 主要有2種用法: (1)限定作用域,比如 修飾全域性變數-全域性靜態變數; 修飾函式-靜態函式。 (2)保持變數內容持久化; 修飾區域性變數-區域性靜態變數。
*修飾全域性變數-全域性靜態變數 在全域性變數前加上關鍵字static,全域性變數就定義成一個全域性靜態變數(限定作用域)。 全域性靜態變數作用域被限制,旨在定義它的檔案之內可見,準確的說是從定義之初開始,到檔案結尾。 在函式返回型別前加關鍵字ststic,函式就成靜態函式。靜態函式只是在定義它的檔案當中可見,不能被其他檔案所用。
使用原則:(1)某一個函式不想被其他模組所引用,則使用static進型修飾; (2)不同的檔案可能函式名有相同,此時使用static進行修飾可以解決重名的問題。
*修飾區域性變數-區域性靜態變數 在區域性變數之前加上關鍵字static,區域性變數就成為一個區域性靜態變數。 作用域:作用域任為區域性作用域,當定義它的函式或者語句塊結束的時候,作用域結束。但是當局部變數靜態變數離開作用域後,並沒有銷燬,而是任然駐留在記憶體當中,該函式再次被呼叫,其值和前次呼叫退出時一樣。 區域性變數是定義在棧上,函式退出後變數就銷燬。 區域性靜態變數是定義在靜態區,其在程式開始執行時就已經在記憶體裡面。
5.記憶體佈局 c語言程式在記憶體執行時主要分為四個區:(1)程式碼區,(2)靜態區,(3)堆區,(4)棧區(大部分情況下,我們只需要理解這四個區就可以了)。
程式碼區: 程式碼區(code area),通常是指用來存放程式執行程式碼的一塊記憶體區域。這部分的區域大小在程式執行前就已經確定。並且記憶體區域通常屬於只讀。在程式碼段中,也有可能包含一些只讀的常量變數,例如字串常量等。
靜態區: 靜態區儲存的內容是程式載入到記憶體的時候就確定,程式退出的時候從記憶體消失。 所有的全域性變數/全域性靜態變數和區域性靜態變數都儲存到靜態區,在程式執行期間都佔用生命週期;靜態區儲存的變數生命週期從程式執行時開始,直到程式結束。
棧區: 棧stack是一種先進後出的結構,由編譯器自動分配釋放記憶體,存放函式的引數值,區域性變數的值等。
(1)函式呼叫先進後出; (2)函式入棧是由高地址往低地址變化; (3)函式呼叫入棧佔用的空間和出棧時要釋放的空間是相等的。 (4)函式呼叫棧的深度由函式棧上分配的空間決定,如果分配較大的陣列則棧會比較深; (5)棧上不能分配太大的陣列(比如2M去試試),否則棧會溢位,導致程式崩潰。 (6)棧變數的生命週期,它是在函式執行的時候開始,直到函式呼叫結束時棧退出(生命週期和作用域是沒有關係的)。
堆區: 也叫動態記憶體分配區域,即由程式設計師自己負責分配和釋放記憶體的區域。 和棧區的區別: (1)棧區分配的空間不能太大,一般不能超過2M;堆區可以分配較大的記憶體空間,只要記憶體足夠大(分配100M/1000M都沒有問題)。 (2)棧區的變數空間由系統自動分配和釋放;堆區要程式設計師自己申請(malloc)和釋放(free),不主動釋放會引起記憶體洩露。