關於C中數組越界問題的解釋

首先,我請你來分析一下這段C語言代碼的運行結果:

int main(int argc, char* argv[]){
    int i = 0;
    int arr[3] = {0};
    for(; i<=3; i++){
        arr[i] = 0;
        printf("hello world\n");
    }
    return 0;
}

你發現問題了嗎?這段代碼的運行結果並非是打印三行“hello word”,而是會無限打印“hello world”,這是爲什麼呢?

因爲,數組大小爲3,a[0],a[1],a[2],而我們的代碼因爲書寫錯誤,導致for循環的結束條件錯寫爲了i<=3而非i<3,所以當i=3時,數組a[3]訪問越界。

我們知道,在C語言中,只要不是訪問受限的內存,所有的內存空間都是可以自由訪問的。根據我們前面講的數組尋址公式,a[3]也會被定位到某塊不屬於數組的內存地址上,而這個地址正好是存儲變量i的內存地址,那麼a[3]=0就相當於i=0,所以就會導致代碼無限循環。

 

問題點在於:a[3]也會被定位到某塊不屬於數組的內存地址上,而這個地址正好是存儲變量i的內存地址,那麼a[3]=0就相當於i=0。

爲什麼就無限循環了?爲什麼a[3] = 0 時,就相當於i=0,就無限循環了呢?

 

合理解釋爲:

函數體內的局部變量存在棧上,且是連續壓棧。在Linux進程的內存佈局中,棧區在高地址空間,從高向低增長。變量i和arr在相鄰地址,且i比arr的地址大,所以arr越界正好訪問到i。當然,前提是i和arr元素同類型,否則那段代碼仍是未決行爲。

 

 

棧是由高到低位增長的,所以,i和數組的數據從高位地址到低位地址依次是:i, a[2], a[1], a[0]。a[3]通過尋址公式,計算得到地址正好是i的存儲地址,所以a[3]=0,就相當於i=0.

紫色部分,目前還是有疑問。尚待解決

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章