1. 程式人生 > >C語言有趣問題_區域性變數的棧空間分配

C語言有趣問題_區域性變數的棧空間分配

有時候,在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次)。