(排版不好,見諒)
先說簡單的:
像這樣 int i = 0; 的語句編譯器會將變量 i 放入棧中,當過了它的作用域之后會自動釋放它在棧中所占的空間。
再有:我們定義了一個類 A ,然后執行語句 A a = new A; 那么 a 這個變量就被編譯器丟到了堆中。
此時 a 中所占的空間只能靠我們自己釋放。
再比如我們定義一個數組 int _i_arr[5]; 毫無疑問那么這個數組也會放到棧中(好象是廢話)。
如果這兩句語句連續起來
int i = 0;
int _i_arr[5];
那么在棧中變量的位置大致上就是
0x000000:
0x00004b: _i_arr(此處向上還有 4*5 個字節屬于 _i_arr)
0x000050: i = 0
0xffffff:
編譯器按照變量定義的順序在內存中由高地址向低地址方向進行字節占用。
如果變態一點這樣寫
int _i_v_arr[-1];
int i = 0;
int _i_arr[5];
編譯器不支持,呵呵。換種方式:
int getInt()
{
return -1;
}
int main()
{
int _i_v_arr[getInt()];
int i = 0;
int _i_arr[5];
return 0;
}
呵呵,這下支持了(g++),我們騙過了編譯器。但是回過頭來想想 _i_v_arr 是在運行時才能確定大小的,
那它實在堆上還是在棧上呢?從語法上來看應該是在棧上的。那它在內存中的布局是怎么樣的呢?
0x000000:
0x000038: _i_v_arr
0x00004b: _i_arr(此處向上還有 4*5 個字節屬于 _i_arr)
0x000050: i = 0
0xffffff:
按照我們之前得出的規律:編譯器按照變量定義的順序在內存中由高地址向低地址方向進行字節占用。
但是這里就違反了,本來 _i_v_arr 是最先定義的,按理說應該在變量 i 的下面(比0x000050要大)
,但是_i_v_arr去跑到了最上面。再定義一個數量是不確定的數組
int getInt()
{
return -1;
}
int main()
{
int _i_v_arr[getInt()];
int _i_v_arr_1[getInt()];
int i = 0;
int _i_arr[5];
return 0;
}
通過觀察我們發現,在內存中的 _i_v_arr_1 在 _i_v_arr 的上面(_i_v_arr_1 的地址小于 _i_v_arr 的地址)
如果單看這兩個動態數組,那他們在內存中位置是符合我們之前的結論的。
于是我們這樣理解,編譯器在入棧的時候先在編譯時期按照能夠明確的變量一次入棧,然后再將到運行時才能明確的變量進行入棧。
另外還有個 sizeof() 函數的問題:
int i = 0;
cout << sizeof(i) << endl;
輸出是 4.
再看下面:
int i = -1;
if(i < sizeof(i))
{
cout << "i < sizeof(i)" << endl;
}else
{
cout << "i > sizeof(i)" << endl;
}
按常理來講,-1 是肯定小于 sizeof(i),但是結果正好跟我們預料的相反。因為sizeof(i)返回的是無符號類型,
跟 INT 做比較運算就會將 i 做轉換,此時進行比較的 i值已經不是 -1 了。這點一定要注意。
再有代碼:
int getInt()
{
return -1;
}
int main()
{
int _i_v_arr[getInt()];
cout << sizeof(_i_v_arr) << endl;
int i = 0;
int _i_arr[5];
return 0;
}
此時的sizeof居然可以輸出 -4 ,天哪。
很奇怪,當 sizeof 返回小于0的值得時候跟 int 的比較就很正常,但是當 sizeof 的返回值大于等于0的時候就會有 int 類型與無符號類型進行類型轉換的問題。
我估計這是 G++ 的BUG。