看似簡單的一段程序如下:
?int main()
{
?? int i,j[8];
?? for(i=0;i<=8;i++)
??? j[i]=0;
?? return 0;
}?
??? gcc編譯運行會陷入死循環.??
?
??? 因為變量 i 和數組 j[8]是保存在棧中,默認是由高地址向低地址方向存儲. 輸出變量地址可以發現: i 存儲位置在0xbfd90dec, j[0]、j[1]...j[7]在內存的地址分別是0xbfdab05c、0xbfdab060,...0xbfdab078. 如下所示:
???????? ?高地址 <--------------------------------------->低地址
???????????????????? ?? ? ?i,j[7],j[6],j[5],j[4],j[3],j[2],j[1],j[0]
?
??? 如果在int i,j[8]后面再定義變量int c,那么c就存放在j[0]的往低方向的下一個地址0xbfdab058 .
????? 現在不難理解這段程序為什么會出現死循環了。j[8]的位置就是變量i所在的位置。這樣當i=8時的j[i]=0語句,實際上就是將i的值置為0,然后 i 又從0到8循環一直下去.?
如果將原句改為int j[8],i; 就不會出現死循環,而僅僅是一個段越界錯誤.
另一個程序:
#include <stdio.h>
int main()
{
??????? int i;
??????? char c;
??????? for(i=0;i<5;i++)
??????? {
??????????????? scanf("%d",&c);
??????????????? printf("i=%d ",i);
??????? }
??????? printf("\n");
}
編譯后運行
[foxman@local~]#./a.out
0??? (輸入0)
i=0? (輸出 i 值)
1
i=0
2
i=0
3
i=0
4
i=0
...
這樣一直循環下去。
問題在于,c被聲明為char類型,而不是int類型。當程序要求scanf讀入一個整數時,應該傳遞給它一個指向整數的指針。而程序中scanf得到的卻是一個指向字符的指針,scanf函數并不能分辨這種情況,只能將這個指向字符的指針作為指向整數的指針而接受,并且在指針指向的位置存儲一個整數。因為整數所占的存儲空間要大于字符所占的存儲空間,所以c附近的內存會被覆蓋.
由上面分析,i 和 c 是由高地址到低地址存儲在棧中,這樣在c所在位置嘗試存儲一個4字節變量,會占用比c高的3個字節(覆蓋掉 i 字節的低3位),即使 i 總是為零,一直循環下去.
如果每次輸入Ctrl+D作為字符終止符不存儲int到c處,那么就會輸出正常i=0..4了.