C語言有趣問題_區域性變數的棧空間分配
阿新 • • 發佈:2019-02-14
有時候,在C語言的迴圈中,如果程式設計時對邊界判斷錯誤,就會帶來意想不到的結果,小白在本文中提及一個有趣的C語言問題,此問題並不是小白原創,而是一本程式設計書的考核內容,小白將其分享到此。
C語言有趣的問題##
先看程式碼:
#include <stdio.h>
int main(void)
{
int a[10];
int i;
for(i = 0; i<=10; ++i)
{
a[i] = 0;
}
/* .... */
}
這是一段最簡單不過的陣列初始化程式碼了,可是因為邊界判斷錯誤,導致陣列訪問越界,執行時出現問題。
Linux環境下,執行程式,結果如下:
出現的結果,直接報出棧粉碎錯誤,程式奔潰。
win10環境下,執行程式,結果如下:
出現的結果,程式一直在執行,並沒有奔潰。
對於Linux的結果,程式直接奔潰,報出了關於棧的問題,不容易發現問題。我們從win10的結果中分析,為什麼程式會進入死迴圈??要想完整回答這個問題,需要認識C語言區域性變數的棧空間分配。
區域性變數的棧空間分配
我們知道,函式區域性變數是呼叫該函式的時候才進行記憶體分配的,如果有多個區域性變數,那麼變數的分配應該有一個順序,C語言對區域性變數的分配機制是採用棧的方式,貼出棧的概念圖:
void fun(int a,int b)
{
int c;
int d;
/* ... */
}
那麼呼叫這個函式的時候,區域性變數分配順序是c、d、a、b,也就是先從上到下順序分配區域性變數,再從左往右順序分配引數。
回答程式進入死迴圈的問題
現在可以完整回答程式為什麼會進入死迴圈了,按照區域性變數的棧空間分配,程式中變數儲存順序如下:
對於
for(i = 0; i<=10; ++i)
{
a[i] = 0;
}
最後的a[10]經過地址計算a+10之後就會指向變數 i 所在的記憶體,然後賦值為0,於是迴圈變數 i 又從10變到0,再次開啟下一次迴圈,周而復始,於是出現了死迴圈。
可以驗證這一說法,只需要輸出 i 的值檢視即可:
for(i = 0; i<= 10; ++i)
{
a[i] = 0;
printf("i=%d\n",i);
}
win10執行結果:
最後,for迴圈中應該遵循左閉右開的區間規則,因為非常容易閱讀出迴圈次數,而上述的左閉右閉,閱讀的時候還要心算一會兒(10-0+1=11次)。