本文轉至
今天看到《c陷阱與缺陷》書中的一段**:
int i,a[10];
for(i=1;i<=10;i++)
a[i]=0;
書中說:在for語句的比較部分本來是i<10;卻寫成了i<=10;因此實際上並不存在的a[10]被設定為0,也就是內存在陣列a之後的乙個字(word)的記憶體被設定為0。如果用來編譯這段程式的編譯器按照記憶體位址遞減的方式來給變數分配記憶體,那麼記憶體中陣列a之後的乙個字(word)實際上是分配給了整型變數i。此時本來迴圈計數器i的值為10,迴圈體內將並不存在的a[10]設定為0,實際上卻是將計數器i的值設定為0,這就陷入死迴圈。
看完後不明白書中說的「編譯器按照記憶體位址遞減的方式來給變數分配記憶體」以及為什麼會陷入死迴圈,於是在vc6.0下作了試驗。
測試程式1:
#include
void main()
結果輸出為:0x12ff7c 0x12ff78
可見,雖然i在j之前被定義,但在編譯器給變數分配記憶體時採用了記憶體位址遞減的方式,所以j在記憶體中的位置比i超前了4個位元組(因為是整型)。回到本文開頭的程式,又做了如下試驗。
測試程式2:
#include
void main()
結果輸出為:0x0012ff7c 0x0012ff54 0x0012ff58 0x0012ff5c 0x0012ff60 0x0012ff64 0x0012ff68 0x0012ff6c 0x0012ff70 0x0012ff74 0x0012ff78
可見對於語句int i,a[10];編譯器在分配記憶體位址時也是按照記憶體位址遞減的方式進行分配;因此在記憶體中實際的變數位址分配為從&a[0]~&a[9],緊接著是&i,即:
0x0012ff54 0x0012ff58 0x0012ff5c 0x0012ff60 0x0012ff64 0x0012ff68 0x0012ff6c 0x0012ff70 0x0012ff74 0x0012ff78 0x0012ff7c
此時就好理解原文中的後半句:因為實際上並不存在a[10],理論上的a[10]就是陣列a之後的乙個記憶體位址,由於編譯器按照記憶體位址遞減的方式給變數分配記憶體,這正好就是變數i的位址,即&a[10]==&i;所以迴圈體中a[10]=0;當i等於10時,a[10]=0;實則為i=0。為了驗證所想是否正確,繼續做了以下試驗。
測試程式3:
#include
void main()
結果輸出為:0x0012ff7c 0x0012ff7c
可見i與a[10]的記憶體位址確實是相同的。
記憶體的分配方式
對於我們初學者來說,記憶體是個神秘的空間。程式的絕大部分錯誤,也是在於記憶體的使用不當造成的,而且這些錯誤有些都是隱藏很深的。所以,如何掌握記憶體的使用,通曉系統對記憶體的管理手段,將是軟體成功的乙個非常關鍵的因素。首先我們要了解記憶體的分配方式。一般來說,記憶體的分配方式有三種 1 從靜態儲存區域...
記憶體的分配方式
關於記憶體的分配方式 靜態儲存區 自由儲存區 堆區和棧區。他們的功能不同,對他們使用方式也就不同。靜態儲存區 內存在程式編譯的時候就已經分配好,這塊內存在程式的整個執行期間都存在。它主要存放靜態資料,全域性資料。棧區 在執行函式時,函式 包括main函式 內區域性變數的儲存單元都可以在棧上建立,函式...
記憶體的分配方式
記憶體的分配方式有幾種?解 1 從靜態儲存區域分配。內存在程式編譯的時候就已經分配好,這塊內存在程式的整個執行期間都存在。例如全域性變數,static變數。2 在棧上建立。在執行函式時,函式內區域性變數的儲存單元都可以在棧上建立,函式執行結束時這些儲存單元自動被釋放。棧記憶體分配運算內置於處理器的指...