c語言動態記憶體分配_C語言之指標的基礎與儲存空間的分配
技術標籤:c語言動態記憶體分配
1.指標基礎
泛型指標與型別轉換泛型指標和型別轉換是用來跨越和覆蓋C語言的型別系統的途徑。泛型指標指向某一資料而不需要理會資料的具體型別。型別轉換允許臨時地改變資料的型別。函式指標指標指向可執行程式碼段或指向呼叫可執行程式碼段的資訊塊,而不是指向某種具體資料。它們把函式當做一小段資料來儲存和管理。
Figure 2.1. An illustration of some operations with pointers
對於其他型別的任何變數,除非我們顯式地指定過,否則我們都不應該假設它指向一個有效的地址。同樣需要記住的是,在C語言中,我們無法改變的一個事實就是指標能夠指向一個無效的地址。指向無效地址的指標有時被稱為懸空指標。可能產生懸空指標的一些程式設計錯誤示例包括:將任意的整型變數強制轉換為指標變數;操作超出陣列邊界的指標;釋放一個或多個仍被引用的指標。
2.儲存空間分配
當在C中宣告一個指標時,與宣告其他型別的變數類似,一定量的儲存空間會分配給這個指標。通常情況下指標會佔用一個機器字長的儲存空間,但有些時候它們的大小也有所不同。因此,為了保證程式碼的可移植性,不應該假設每個指標都佔有一個特定大小的儲存空間。指標變數的大小通常與編譯器的設定以及某些特定的C實現中的型別界定符有關。必須要記住的一點是:當宣告一個指標時,僅僅只是為指標本身分配了空間,並沒有為指標所引用的資料分配空間。而為資料分配儲存空間有兩種方法:一種是直接宣告一個變數;另一種是在執行時動態地分配儲存空間(例如:使用malloc或realloc)。
當宣告一個變數時,編譯器會根據變數的型別預留足夠的記憶體空間。變數的儲存空間是系統自動分配的,但此儲存空間不會在程式的整個生命週期中永久存在,這一點在處理自動變數時尤為重要。自動變數是一種在進入或離開一個模組或函式時其儲存空間能夠自動分配和釋放的變數。例如:在函式f中,iptr的賦值為變數a的地址,當函式f返回時,iptr變成了一個懸空指標。為什麼會這樣?因為當函式f返回時,變數a已經從函式棧中彈出,變成了一個不合法的變數。
int f(int **iptr) {int a = 10;*iptr = &a;return 0;}
在C語言中,當想要動態分配儲存空間時,我們會得到一個指向一個堆儲存空間的指標(見第3章)。此儲存空間由我們自行管理,並且會一直存在,除非我們顯式地將它釋放。例如:在下面這段程式碼中用malloc分配的儲存空間會一直有效直到呼叫函式free來釋放它。所以,當函式g返回時此儲存空間仍然有效(見圖2-2),這一點與之前自動分配儲存空間的變數完全不同。引數iptr是一個指向我們想要改變其內容的物件的指標(此物件也是一個指標),所以當g返回時,iptr指向由malloc申請的地址空間。
#include int g(int **iptr) {if ((*iptr = (int *)malloc(sizeof(int))) == NULL) return -1;return 0;}
Figure 2.2. Pointer operations in returning storage dynamically allocated in a function
有些時候,我們甚至會認為指標和動態儲存空間分配是C語言領域中不太好的特性。特別是當生產了由動態記憶體分配所造成的記憶體洩漏問題時。記憶體洩漏問題的產生是由於動態分配了記憶體空間,但從未釋放它(甚至在程式不再使用此資料空間時都不釋放它)造成的。
特別是在重複執行程式碼時,這種洩漏問題會表現得尤為嚴重。好在我們可以採用統一的記憶體管理方法來大大減少此類問題。一種統一的記憶體管理方法例子就是本書中所用到的資料結構例項。 每種例項所遵循的理念是,由使用者來管理儲存空間以及與儲存空間相關的實際的資料結構,而資料結構自身只用於維護資料內部變數的儲存空間分配。所以,在資料結構中,只使用指標所指向資料變數,而不是此資料的私有副本。這種應用的一個重要意義在於,一個數據結構的實現並不依賴於它所儲存的資料的型別和大小。同時,多個數據結構能夠以單個數據形態表現,這個特性在組織大量資料時非常有用。
有些時候,我們甚至會認為指標和動態儲存空間分配是C語言領域中不太好的特性。特別是當生產了由動態記憶體分配所造成的記憶體洩漏問題時。記憶體洩漏問題的產生是由於動態分配了記憶體空間,但從未釋放它(甚至在程式不再使用此資料空間時都不釋放它)造成的。特別是在重複執行程式碼時,這種洩漏問題會表現得尤為嚴重。好在我們可以採用統一的記憶體管理方法來大大減少此類問題。一種統一的記憶體管理方法例子就是本書中所用到的資料結構例項。每種例項所遵循的理念是,由使用者來管理儲存空間以及與儲存空間相關的實際的資料結構,而資料結構自身只用於維護資料內部變數的儲存空間分配。所以,在資料結構中,只使用指標所指向資料變數,而不是此資料的私有副本。這種應用的一個重要意義在於,一個數據結構的實現並不依賴於它所儲存的資料的型別和大小。同時,多個數據結構能夠以單個數據形態表現,這個特性在組織大量資料時非常有用。